source: Swollen/swollen/main.cpp @ 668

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

Last release version changes

File size: 12.4 KB
RevLine 
[6]1/*
[106]2  SWWViewer
[6]3
[106]4  An OpenSceneGraph viewer for pyVolution SWW files.
5  copyright (C) 2004-2005 Geoscience Australia
[6]6*/
7
[121]8#include <iostream>
9#include <fstream>
10
[6]11#include <osg/Group>
12#include <osg/Material>
13#include <osg/MatrixTransform>
14#include <osg/Notify>
15#include <osg/PositionAttitudeTransform>
16#include <osg/StateAttribute>
[106]17#include <osgDB/FileNameUtils>
[6]18
[125]19#include <animation.h>
[6]20#include <project.h>
21#include <SWWReader.h>
22#include <bedslope.h>
23#include <hud.h>
24#include <keyboardeventhandler.h>
[72]25#include <directionallight.h>
[113]26#include <state.h>
[6]27#include <watersurface.h>
[92]28#include <customviewer.h>
[121]29#include <customargumentparser.h>
[6]30
31// prototypes
[106]32osg::Transform* createSky(float radius, const std::string filename);
[67]33extern const char* version();
[6]34
35
36int main( int argc, char **argv )
37{
[37]38
[121]39   // use an ArgumentParser object to manage the program arguments.
[125]40   // this custom version detects if the last argument is a macro file
[121]41   // and modifies the argument list accordingly so the following code works ...
42   CustomArgumentParser arguments( &argc, argv );
[119]43
[6]44
[106]45   // set up the usage document
46   std::string appname = arguments.getApplicationName();
47   arguments.getApplicationUsage()->setDescription( appname );
48   arguments.getApplicationUsage()->setCommandLineUsage("swollen [options] swwfile ...");
[121]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");
[132]58   arguments.getApplicationUsage()->addCommandLineOption("-loop", "Repeated (looped) playback of .swm files");
[121]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");
[38]63
[119]64
[106]65   // construct the viewer.
66   CustomViewer viewer(arguments);
[6]67
[121]68
[106]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 );
[6]74
75
[125]76   // animation
77   StateList statelist;
78   bool playbackmode;
79   bool recordingmode = false;
80   bool savemovie = false;
[132]81   bool loop = false;
[125]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      }
[132]96      if( arguments.read("-loop") ) 
97         loop = true;
[125]98   }
99   else
100   {
101      playbackmode = false;
102      savemovie = false;
[132]103      loop = true;  // playback in none macro mode should loop (otherwise you don't get a chance to save)
[125]104   }
105
106
[106]107   // get details on keyboard and mouse bindings used by the viewer
108   viewer.getUsage(*arguments.getApplicationUsage());
[6]109
[106]110   // if user requested help, write it out to cout
[125]111   if( arguments.read("-help") || arguments.read("--help") || arguments.read("-h") )
[106]112   {
113      arguments.getApplicationUsage()->write(std::cout);
114      return 1;
115   }
[6]116
[121]117
[106]118   // same for version info
119   if( arguments.read("-version") )
120   {
121      std::cout << version() << std::endl;
122      return 1;
123   }
[6]124
[66]125
[119]126   // last argument is either an sww file or an swm macro recording
[106]127   int lastarg = arguments.argc()-1;
128   std::string swwfile = arguments.argv()[lastarg];
129   arguments.remove(lastarg);
[132]130   if( osgDB::getLowerCaseFileExtension(swwfile) != std::string("sww") )
[106]131   {
[121]132      std::cout << "Require last argument be an .sww/.swm file ... quitting" << std::endl;
[106]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   }
[6]141
142
[106]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]) );
[6]148
[74]149
[106]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 );
[6]159
[106]160   std::string bedslopetexture;
161   if( arguments.read("-texture",bedslopetexture) ) sww->setBedslopeTexture( bedslopetexture );
[6]162
[106]163   // root node
164   osg::Group* rootnode = new osg::Group;
[6]165
[106]166   // transform
167   osg::PositionAttitudeTransform* model = new osg::PositionAttitudeTransform;
168   model->setName("position_attitude_transform");
[6]169
[106]170   // enscapsulates OpenGL state
171   osg::StateSet* rootStateSet = new osg::StateSet;
[6]172
[106]173   // Bedslope geometry
174   BedSlope* bedslope = new BedSlope(sww);
[6]175
[106]176   // Water geometry
177   WaterSurface* water = new WaterSurface(sww);
[45]178
[106]179   // Heads Up Display (text overlay)
180   HeadsUpDisplay* hud = new HeadsUpDisplay();
181   hud->setTitle("pyVolution SWW Viewer");
[125]182   if( arguments.isSWM() )
183      hud->setMode("playback");
[6]184
[45]185
[106]186   // Lighting
187   DirectionalLight* light = new DirectionalLight(rootStateSet);
188   light->setPosition( osg::Vec3(1,1,1) );  // z is up
[100]189
[106]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   }
[100]198
[6]199
[11]200
[106]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() );
[11]208
[6]209
[106]210   // allow vertical scaling from command line parameter
211   model->setScale( osg::Vec3(1.0, 1.0, vscale) );
[6]212
[106]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);
[6]220 
[106]221   // any option left unread are converted into errors to write out later.
222   arguments.reportRemainingOptionsAsUnrecognized();
[6]223 
[106]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   }
[6]230
[111]231
[106]232   // register additional event handler
233   KeyboardEventHandler* event_handler = new KeyboardEventHandler(sww->getNumberOfTimesteps(), tps);
234   viewer.getEventHandlerList().push_front(event_handler);
[45]235
[6]236 
[106]237   // create the windows and run the threads.
238   viewer.realize();
[6]239
240
[106]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();
[66]251
[114]252 
[106]253   unsigned int timestep = 0;
[132]254   bool done = false;
255   while( !done )
[106]256   {
[71]257   
[106]258      // wait for all cull and draw threads to complete.
259      viewer.sync();
[6]260
[132]261      // user hits 'escape' to exit
262      if( viewer.done() )
263         done = true;
[105]264
[132]265
[115]266      if( !playbackmode )
267      {
[6]268
[115]269         // current time
270         double time = viewer.getFrameStamp()->getReferenceTime();
271
272         event_handler->setTime( time );
[106]273         timestep = event_handler->getTimestep();
274         water->setTimeStep(timestep);
275         hud->setTime( sww->getTime(timestep) );
[66]276
[13]277
[115]278         // events
279         if( event_handler->toggleWireframe() )
280            water->toggleWireframe();
281         if( event_handler->toggleCulling() )
[116]282            water->toggleCulling();
[111]283
[115]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; 
[116]291                  hud->setMode("recording");
[115]292                  break;
293               case true : 
294                  recordingmode = false; 
[116]295                  hud->setMode("");
[115]296                  break;
297            }
298         }
[111]299
300
[115]301         // '2' key starts playback of recorded frames
[116]302         if( event_handler->togglePlayback() && statelist.size() > 0 )
[115]303         {
304            recordingmode = false;
[116]305            playbackmode = true; 
306            hud->setMode("playback");
307            event_handler->setPaused( true );
308            playback_index = 0;
[115]309         }
[111]310
[115]311         if( recordingmode )
[111]312         {
[116]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 );
[111]319         }
320      }
321
[115]322      else
323
[114]324      {
[125]325         // might need to save image from previous pass ...
326         if( savemovie )
327            animation.saveImage( playback_index );
328
[115]329         // in playback mode
[116]330         State state = statelist.at( playback_index );
331         water->setTimeStep( state.getTimestep() );
332         water->setWireframe( state.getWireframe() );
333         water->setCulling( state.getCulling() );
[119]334         hud->setTime( sww->getTime(state.getTimestep()) );
[115]335
336         // loop playback
337         playback_index ++;
338         if( playback_index == statelist.size() )
[132]339         {
340            if( loop )
341               playback_index = 0;
342            else
343               done = true;
344         }
[116]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() );
[114]355      }
[111]356
[125]357
[116]358      // '3' key causes compiled animation to be saved to disk
359      if( event_handler->toggleSave() )
[119]360      {
[121]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         }
[132]371         std::cout << "Wrote macro file movie.swm" << std::endl;
[119]372      }
[113]373
[116]374      // scene-graph updates
375      bedslope->update();
376      hud->update();
377      water->update();
378
[106]379      // update the scene by traversing with the update visitor
380      viewer.update();
[115]381
[106]382      // fire off the cull and draw traversals of the scene.
383      viewer.frame();
384   }
[6]385   
[106]386   // wait for all cull and draw threads to complete before exit.
387   viewer.sync();
[6]388
[106]389   return 0;
[6]390}
Note: See TracBrowser for help on using the repository browser.