From 3bce3122131dbdb2c00e44f83b2fb876d4939c9a Mon Sep 17 00:00:00 2001 From: timoore Date: Mon, 10 Aug 2009 21:43:55 +0000 Subject: [PATCH] Get fgviewer working as a part of fgfs Move fgviewer code into fgfs binary. Its osgViewer-style main function is called from bootstrap.cxx if the --fgviewer argument is passed to fgfs. Use fgfs initialization functions in fgviewer codepath. Read command-line arguments and autosave.xml. --- projects/VC7.1/FlightGear.vcproj | 7 + src/Main/Makefile.am | 1 + src/Main/bootstrap.cxx | 13 +- src/Main/fgviewer.cxx | 242 +++++++++++++++++++++++++++++++ src/Main/fgviewer.hxx | 5 + src/Main/options.cxx | 10 ++ 6 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 src/Main/fgviewer.cxx create mode 100644 src/Main/fgviewer.hxx diff --git a/projects/VC7.1/FlightGear.vcproj b/projects/VC7.1/FlightGear.vcproj index 317a3a6b2..55c10c9f9 100755 --- a/projects/VC7.1/FlightGear.vcproj +++ b/projects/VC7.1/FlightGear.vcproj @@ -1876,6 +1876,13 @@ + + + + + diff --git a/src/Main/Makefile.am b/src/Main/Makefile.am index 9ff54a2ed..041e69033 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -40,6 +40,7 @@ noinst_LIBRARIES = libMain.a libMain_a_SOURCES = \ main.cxx main.hxx \ renderer.cxx renderer.hxx \ + fgviewer.cxx fgviewer.hxx \ fg_commands.cxx fg_commands.hxx \ fg_init.cxx fg_init.hxx \ fg_io.cxx fg_io.hxx \ diff --git a/src/Main/bootstrap.cxx b/src/Main/bootstrap.cxx index 9f2fcbb6d..f4c24345d 100644 --- a/src/Main/bootstrap.cxx +++ b/src/Main/bootstrap.cxx @@ -51,6 +51,7 @@ using std::endl; #include "main.hxx" #include "globals.hxx" +#include "fgviewer.hxx" #include "fg_os.hxx" @@ -208,13 +209,23 @@ int main ( int argc, char **argv ) { #if defined( HAVE_BC5PLUS ) _control87(MCW_EM, MCW_EM); /* defined in float.h */ #endif + bool fgviewer = false; + for (int i = 0; i < argc; ++i) { + if (!strcmp("--fgviewer", argv[i])) { + fgviewer = true; + break; + } + } // FIXME: add other, more specific // exceptions. try { std::set_terminate(fg_terminate); atexit(fgExitCleanup); - fgMainInit(argc, argv); + if (fgviewer) + fgviewerMain(argc, argv); + else + fgMainInit(argc, argv); } catch (const sg_throwable &t) { // We must use cerr rather than // logging, since logging may be diff --git a/src/Main/fgviewer.cxx b/src/Main/fgviewer.cxx new file mode 100644 index 000000000..6e6e040b7 --- /dev/null +++ b/src/Main/fgviewer.cxx @@ -0,0 +1,242 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "fg_init.hxx" +#include "fg_props.hxx" +#include "globals.hxx" +#include "options.hxx" + +class DummyLoadHelper : public simgear::ModelLoadHelper { +public: + virtual osg::Node *loadTileModel(const string& modelPath, bool) + { + try { + SGSharedPtr prop = new SGPropertyNode; + return simgear::SGModelLib::loadModel(modelPath, prop); + } catch (...) { + std::cerr << "Error loading \"" << modelPath << "\"" << std::endl; + return 0; + } + } +}; + +class GraphDumpHandler : public osgGA::GUIEventHandler +{ +public: + GraphDumpHandler() : _keyDump('d') {} + void setKeyDump(int key) { _keyDump = key; } + int getKeyDump() const { return _keyDump; } + bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa); + + /** Get the keyboard and mouse usage of this manipulator.*/ + virtual void getUsage(osg::ApplicationUsage& usage) const; +protected: + int _keyDump; +}; + +static void dumpOut(osg::Node* node) +{ + char filename[24]; + static int count = 1; + + FGRenderer *renderer = globals->get_renderer(); + + while (count < 1000) { + FILE *fp; + snprintf(filename, 24, "fgviewer-%03d.osg", count++); + if ( (fp = fopen(filename, "r")) == NULL ) + break; + fclose(fp); + } + + if (osgDB::writeNodeFile(*node, filename)) + std::cerr << "Entire scene graph saved to \"" << filename << "\".\n"; + else + std::cerr << "Failed to save to \"" << filename << "\".\n"; +} + +bool GraphDumpHandler::handle(const osgGA::GUIEventAdapter& ea, + osgGA::GUIActionAdapter& aa) +{ + osgViewer::View* view = dynamic_cast(&aa); + if (!view) + return false; + if (ea.getHandled()) + return false; + switch(ea.getEventType()) { + case osgGA::GUIEventAdapter::KEYUP: + if (ea.getKey() == _keyDump) { + dumpOut(view->getScene()->getSceneData()); + return true; + } + break; + default: + return false; + } +} + +void GraphDumpHandler::getUsage(osg::ApplicationUsage& usage) const +{ + std::ostringstream ostr; + ostr << char(_keyDump); + usage.addKeyboardMouseBinding(ostr.str(), + "Dump scene graph to file"); +} + +int +fgviewerMain(int argc, char** argv) +{ + + sgUserDataInit(0); + DummyLoadHelper dummyLoadHelper; + simgear::TileEntry::setModelLoadHelper(&dummyLoadHelper); + + // use an ArgumentParser object to manage the program arguments. + osg::ArgumentParser arguments(&argc, argv); + + // construct the viewer. + osgViewer::Viewer viewer(arguments); + osg::Camera* camera = viewer.getCamera(); + osgViewer::Renderer* renderer + = static_cast(camera->getRenderer()); + for (int i = 0; i < 2; ++i) { + osgUtil::SceneView* sceneView = renderer->getSceneView(i); + sceneView->setCullVisitor(new simgear::EffectCullVisitor); + } + // Shaders expect valid fog + osg::StateSet* cameraSS = camera->getOrCreateStateSet(); + osg::Fog* fog = new osg::Fog; + fog->setMode(osg::Fog::EXP2); + fog->setColor(osg::Vec4(1.0, 1.0, 1.0, 1.0)); + fog->setDensity(.0000001); + cameraSS->setAttributeAndModes(fog); + // ... for some reason, get rid of that FIXME! + viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded); + + // set up the camera manipulators. + osgGA::KeySwitchMatrixManipulator* keyswitchManipulator; + keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator; + + osgGA::MatrixManipulator* mm = new osgGA::TrackballManipulator; + keyswitchManipulator->addMatrixManipulator('1', "Trackball", mm); + mm = new osgGA::FlightManipulator; + keyswitchManipulator->addMatrixManipulator('2', "Flight", mm); + mm = new osgGA::DriveManipulator; + keyswitchManipulator->addMatrixManipulator('3', "Drive", mm); + mm = new osgGA::TerrainManipulator; + keyswitchManipulator->addMatrixManipulator('4', "Terrain", mm); + + viewer.setCameraManipulator(keyswitchManipulator); + + // Usefull stats + viewer.addEventHandler(new osgViewer::HelpHandler); + viewer.addEventHandler(new osgViewer::StatsHandler); + viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); + // Same FIXME ... + // viewer.addEventHandler(new osgViewer::ThreadingHandler); + viewer.addEventHandler(new osgViewer::LODScaleHandler); + viewer.addEventHandler(new osgViewer::ScreenCaptureHandler); + + viewer.addEventHandler(new GraphDumpHandler); + + // Extract files to load from arguments now; this way fgInitConfig + // won't choke on them. + string_list dataFiles; + for (int i = arguments.argc() - 1; i >= 0; --i) { + if (arguments.isOption(i)) { + break; + } else { + dataFiles.insert(dataFiles.begin(), arguments[i]); + arguments.remove(i); + } + } + + // A subset of full flightgear initialization. + // Allocate global data structures. This needs to happen before + // we parse command line options + + globals = new FGGlobals; + + fgInitFGRoot(arguments.argc(), arguments.argv()); + if ( !fgInitConfig(arguments.argc(), arguments.argv()) ) { + SG_LOG( SG_GENERAL, SG_ALERT, "Config option parsing failed ..." ); + exit(-1); + } + + osgDB::FilePathList filePathList + = osgDB::Registry::instance()->getDataFilePathList(); + filePathList.push_back(globals->get_fg_root()); + + string_list path_list = globals->get_fg_scenery(); + for (unsigned i = 0; i < path_list.size(); ++i) { + filePathList.push_back(path_list[i]); + } + + globals->set_matlib( new SGMaterialLib ); + simgear::SGModelLib::init(globals->get_fg_root()); + + // Initialize the material property subsystem. + + SGPath mpath( globals->get_fg_root() ); + mpath.append( "materials.xml" ); + if ( ! globals->get_matlib()->load(globals->get_fg_root(), mpath.str(), + globals->get_props()) ) { + SG_LOG( SG_GENERAL, SG_ALERT, "Error loading material lib!" ); + exit(-1); + } + + globals->set_scenery( new FGScenery ); + globals->get_scenery()->init(); + globals->get_scenery()->bind(); + + // The file path list must be set in the registry. + osgDB::Registry::instance()->getDataFilePathList() = filePathList; + + SGReaderWriterBTGOptions* btgOptions = new SGReaderWriterBTGOptions; + btgOptions->getDatabasePathList() = filePathList; + btgOptions->setMatlib(globals->get_matlib()); + + // read the scene from the list of file specified command line args. + osg::ref_ptr loadedModel; + loadedModel = osgDB::readNodeFiles(dataFiles, btgOptions); + + // if no model has been successfully loaded report failure. + if (!loadedModel.valid()) { + std::cerr << arguments.getApplicationName() + << ": No data loaded" << std::endl; + return EXIT_FAILURE; + } + + // pass the loaded scene graph to the viewer. + viewer.setSceneData(loadedModel.get()); + + return viewer.run(); +} diff --git a/src/Main/fgviewer.hxx b/src/Main/fgviewer.hxx new file mode 100644 index 000000000..82cdf5ee4 --- /dev/null +++ b/src/Main/fgviewer.hxx @@ -0,0 +1,5 @@ +#ifndef __FG_FGVIEWER_HXX +#define __FG_FGVIEWER_HXX 1 + +int fgviewerMain(int argc, char** argv); +#endif diff --git a/src/Main/options.cxx b/src/Main/options.cxx index 6305fe7f3..685d61ff1 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -1207,6 +1207,15 @@ fgOptFpe(const char* arg) return FG_OPTIONS_OK; } +static int +fgOptFgviewer(const char* arg) +{ + // Actually handled in bootstrap.cxx + return FG_OPTIONS_OK; +} + + + static map fgOptionMap; /* @@ -1417,6 +1426,7 @@ struct OptionDesc { {"parking-id", true, OPTION_FUNC, "", false, "", fgOptParking }, {"version", false, OPTION_FUNC, "", false, "", fgOptVersion }, {"enable-fpe", false, OPTION_FUNC, "", false, "", fgOptFpe}, + {"fgviewer", false, OPTION_FUNC, "", false, "", fgOptFgviewer}, {0} };