/* SWWViewer An OpenSceneGraph viewer for pyVolution SWW files. copyright (C) 2004-2005 Geoscience Australia */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // prototypes osg::Transform* createSky(float radius, const std::string filename); extern const char* version(); int main( int argc, char **argv ) { // use an ArgumentParser object to manage the program arguments. // this custom version detects if the last argument is a macro file // and modifies the argument list accordingly so the following code works ... CustomArgumentParser arguments( &argc, argv ); // set up the usage document std::string appname = arguments.getApplicationName(); arguments.getApplicationUsage()->setDescription( appname ); arguments.getApplicationUsage()->setCommandLineUsage("swollen [options] swwfile ..."); arguments.getApplicationUsage()->addCommandLineOption("-help", "Display this information"); arguments.getApplicationUsage()->addCommandLineOption("-scale ", "Vertical scale factor"); arguments.getApplicationUsage()->addCommandLineOption("-tps ", "Timesteps per second"); arguments.getApplicationUsage()->addCommandLineOption("-hmin ", "Height below which transparency is set to zero"); arguments.getApplicationUsage()->addCommandLineOption("-hmax ", "Height above which transparency is set to alphamax"); arguments.getApplicationUsage()->addCommandLineOption("-alphamin ", "Transparency value at hmin"); arguments.getApplicationUsage()->addCommandLineOption("-alphamax ", "Maximum transparency clamp value"); arguments.getApplicationUsage()->addCommandLineOption("-lightpos ,,", "x,y,z of bedslope directional light (z is up, default is overhead)"); arguments.getApplicationUsage()->addCommandLineOption("-movie ", "Save numbered images to named directory and quit"); arguments.getApplicationUsage()->addCommandLineOption("-loop", "Repeated (looped) playback of .swm files"); arguments.getApplicationUsage()->addCommandLineOption("-nosky", "Omit background sky"); arguments.getApplicationUsage()->addCommandLineOption("-cullangle ", "Cull triangles steeper than this value"); arguments.getApplicationUsage()->addCommandLineOption("-texture ", "Image to use for bedslope topography"); arguments.getApplicationUsage()->addCommandLineOption("-version", "Revision number and creation (not compile) date"); // construct the viewer. CustomViewer viewer(arguments); // set up with sensible default event handlers viewer.setUpViewer( osgProducer::Viewer::STANDARD_SETTINGS ); viewer.setClearColor( osg::Vec4(DEF_BACKGROUND_COLOUR) ); //viewer.getCamera(0)->getRenderSurface()->setWindowRectangle(200,300,400,300); viewer.getCullSettings().setComputeNearFarMode( osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES ); // animation StateList statelist; bool playbackmode; bool recordingmode = false; bool savemovie = false; bool loop = false; unsigned int playback_index = 0; std::string moviedir; Animation animation; if( arguments.isSWM() ) { playbackmode = true; statelist.read( arguments.getFilename() ); if( arguments.read("-movie",moviedir) ) { savemovie = true; // flag to store frames and quit ... animation.setDirectory( moviedir ); animation.setViewer( viewer ); } if( arguments.read("-loop") ) loop = true; } else { playbackmode = false; savemovie = false; loop = true; // playback in none macro mode should loop (otherwise you don't get a chance to save) } // get details on keyboard and mouse bindings used by the viewer viewer.getUsage(*arguments.getApplicationUsage()); // if user requested help, write it out to cout if( arguments.read("-help") || arguments.read("--help") || arguments.read("-h") ) { arguments.getApplicationUsage()->write(std::cout); return 1; } // same for version info if( arguments.read("-version") ) { std::cout << version() << std::endl; return 1; } // last argument is either an sww file or an swm macro recording int lastarg = arguments.argc()-1; std::string swwfile = arguments.argv()[lastarg]; arguments.remove(lastarg); if( osgDB::getLowerCaseFileExtension(swwfile) != std::string("sww") ) { std::cout << "Require last argument be an .sww/.swm file ... quitting" << std::endl; return 1; } SWWReader *sww = new SWWReader(swwfile); if (sww->isValid() == false) { std::cout << "Unable to load " << swwfile << " ... is this really an .sww file?" << std::endl; return 1; } // need swollen binary directory which contains resource images char *ptr; if( (ptr = getenv( "SWOLLEN_BINDIR" )) ) sww->setSwollenDir( std::string(ptr) ); else if( osgDB::getFilePath(argv[0]) == "" ) sww->setSwollenDir( std::string(".") ); else sww->setSwollenDir( osgDB::getFilePath(argv[0]) ); std::cout << sww->getSwollenDir() << std::endl; // default arguments and command line parameters float tmpfloat, tps, vscale; if( !arguments.read("-tps", tps) || tps <= 0.0 ) tps = DEF_TPS; if( !arguments.read("-scale", vscale) ) vscale = 1.0; if( arguments.read("-hmin",tmpfloat) ) sww->setHeightMin( tmpfloat ); if( arguments.read("-hmax",tmpfloat) ) sww->setHeightMax( tmpfloat ); if( arguments.read("-alphamin",tmpfloat) ) sww->setAlphaMin( tmpfloat ); if( arguments.read("-alphamax",tmpfloat) ) sww->setAlphaMax( tmpfloat ); if( arguments.read("-cullangle",tmpfloat) ) sww->setCullAngle( tmpfloat ); std::string bedslopetexture; if( arguments.read("-texture",bedslopetexture) ) sww->setBedslopeTexture( bedslopetexture ); // root node osg::Group* rootnode = new osg::Group; // transform osg::PositionAttitudeTransform* model = new osg::PositionAttitudeTransform; model->setName("position_attitude_transform"); // enscapsulates OpenGL state osg::StateSet* rootStateSet = new osg::StateSet; // Bedslope geometry BedSlope* bedslope = new BedSlope(sww); // Water geometry WaterSurface* water = new WaterSurface(sww); // Heads Up Display (text overlay) HeadsUpDisplay* hud = new HeadsUpDisplay(); hud->setTitle("pyVolution SWW Viewer"); if( arguments.isSWM() ) hud->setMode("playback"); // Lighting DirectionalLight* light = new DirectionalLight(rootStateSet); light->setPosition( osg::Vec3(1,1,1) ); // z is up std::string lightposstr; while (arguments.read("-lightpos",lightposstr)) { float x, y, z; int count = sscanf( lightposstr.c_str(), "%f,%f,%f", &x, &y, &z ); if( count == 3 ) light->setPosition( osg::Vec3(x,y,z) ); // z is up else osg::notify(osg::WARN) << "Invalid bedslope light position \"" << lightposstr << "\"" << std::endl; } // scenegraph hierarchy rootnode->setStateSet(rootStateSet); rootnode->addChild( hud->get() ); rootnode->addChild( light->get() ); rootnode->addChild(model); model->addChild( bedslope->get() ); model->addChild( water->get() ); // allow vertical scaling from command line parameter model->setScale( osg::Vec3(1.0, 1.0, vscale) ); // surrounding sky sphere if( !arguments.read("-nosky") ) rootnode->addChild( createSky(10.0, sww->getSwollenDir() + std::string("/sky_small.jpg") )); // add model to viewer. viewer.setSceneData(rootnode); // any option left unread are converted into errors to write out later. arguments.reportRemainingOptionsAsUnrecognized(); // report any errors if they have occured when parsing the program aguments. if (arguments.errors()) { arguments.writeErrorMessages(std::cout); return 1; } // register additional event handler KeyboardEventHandler* event_handler = new KeyboardEventHandler(sww->getNumberOfTimesteps(), tps); viewer.getEventHandlerList().push_front(event_handler); // create the windows and run the threads. viewer.realize(); // initial camera position CustomTerrainManipulator* terrainmanipulator = viewer.getTerrainManipulator(); terrainmanipulator->setNode( model ); terrainmanipulator->setAutoComputeHomePosition( false ); terrainmanipulator->setHomePosition( osg::Vec3d(0,-3,3), // camera location osg::Vec3d(0,0,0), // camera target osg::Vec3d(0,1,1) ); // camera up vector terrainmanipulator->moveToHome(); terrainmanipulator->enable(); unsigned int timestep = 0; bool done = false; while( !done ) { // wait for all cull and draw threads to complete. viewer.sync(); // user hits 'escape' to exit if( viewer.done() ) done = true; if( !playbackmode ) { // current time double time = viewer.getFrameStamp()->getReferenceTime(); event_handler->setTime( time ); timestep = event_handler->getTimestep(); water->setTimeStep(timestep); hud->setTime( sww->getTime(timestep) ); // events if( event_handler->toggleWireframe() ) water->toggleWireframe(); if( event_handler->toggleCulling() ) water->toggleCulling(); // '1' key starts/stops recording of view/position/setting info if( event_handler->toggleRecording() ) { switch( recordingmode ) { case false : recordingmode = true; hud->setMode("recording"); break; case true : recordingmode = false; hud->setMode(""); break; } } // '2' key starts playback of recorded frames if( event_handler->togglePlayback() && statelist.size() > 0 ) { recordingmode = false; playbackmode = true; hud->setMode("playback"); event_handler->setPaused( true ); playback_index = 0; } if( recordingmode ) { State state = State(); state.setTimestep( event_handler->getTimestep() ); state.setCulling( sww->getCulling() ); state.setWireframe( water->getWireframe() ); state.setMatrix( viewer.getViewMatrix() ); statelist.push_back( state ); } } else { // might need to save image from previous pass ... if( savemovie ) animation.saveImage( playback_index ); // in playback mode State state = statelist.at( playback_index ); water->setTimeStep( state.getTimestep() ); water->setWireframe( state.getWireframe() ); water->setCulling( state.getCulling() ); hud->setTime( sww->getTime(state.getTimestep()) ); // loop playback playback_index ++; if( playback_index == statelist.size() ) { if( loop ) playback_index = 0; else done = true; } // '2' key stops playback of recorded frames if( event_handler->togglePlayback() ) { playbackmode = false; hud->setMode(""); event_handler->setPaused( true ); } viewer.setView( state.getMatrix() ); } // '3' key causes compiled animation to be saved to disk if( event_handler->toggleSave() ) { std::fstream f; f.open( "movie.swm", std::fstream::out ); if( f.is_open() ) { f << "# SWM 1.0 START" << std::endl; arguments.write( f ); statelist.write( f ); f << "# SWM END" << std::endl; f.close(); } std::cout << "Wrote macro file movie.swm" << std::endl; } // scene-graph updates bedslope->update(); hud->update(); water->update(); // update the scene by traversing with the update visitor viewer.update(); // fire off the cull and draw traversals of the scene. viewer.frame(); } // wait for all cull and draw threads to complete before exit. viewer.sync(); return 0; }