]> git.mxchange.org Git - flightgear.git/blob - src/Main/fgviewer.cxx
3ab9570b5536e2abddf714d777f9dca31a743092
[flightgear.git] / src / Main / fgviewer.cxx
1 #include <iostream>
2 #include <cstdlib>
3
4 #include <osg/ArgumentParser>
5 #include <osg/Fog>
6 #include <osgDB/ReadFile>
7 #include <osgDB/Registry>
8 #include <osgDB/WriteFile>
9 #include <osgViewer/Renderer>
10 #include <osgViewer/Viewer>
11 #include <osgViewer/ViewerEventHandlers>
12 #include <osgGA/KeySwitchMatrixManipulator>
13 #include <osgGA/TrackballManipulator>
14 #include <osgGA/FlightManipulator>
15 #include <osgGA/DriveManipulator>
16 #include <osgGA/TerrainManipulator>
17 #include <osgGA/StateSetManipulator>
18
19 #include <simgear/props/props.hxx>
20 #include <simgear/props/props_io.hxx>
21 #include <simgear/misc/sg_path.hxx>
22 #include <simgear/scene/material/EffectCullVisitor.hxx>
23 #include <simgear/scene/material/matlib.hxx>
24 #include <simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx>
25 #include <simgear/scene/tgdb/userdata.hxx>
26 #include <simgear/scene/tgdb/TileEntry.hxx>
27 #include <simgear/scene/model/ModelRegistry.hxx>
28 #include <simgear/scene/model/modellib.hxx>
29
30 #include <Scenery/scenery.hxx>
31
32 #include "fg_init.hxx"
33 #include "fg_props.hxx"
34 #include "globals.hxx"
35 #include "options.hxx"
36
37 class DummyLoadHelper : public simgear::ModelLoadHelper {
38 public:
39     virtual osg::Node *loadTileModel(const string& modelPath, bool)
40     {
41         try {
42             SGSharedPtr<SGPropertyNode> prop = new SGPropertyNode;
43             return simgear::SGModelLib::loadModel(modelPath,
44                                                   globals->get_props());
45         } catch (...) {
46             std::cerr << "Error loading \"" << modelPath << "\"" << std::endl;
47             return 0;
48         }
49     }
50 };
51
52 class GraphDumpHandler : public  osgGA::GUIEventHandler
53 {
54 public:
55     GraphDumpHandler() : _keyDump('d') {}
56     void setKeyDump(int key) { _keyDump = key; }
57     int getKeyDump() const { return _keyDump; }
58     bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
59
60     /** Get the keyboard and mouse usage of this manipulator.*/
61     virtual void getUsage(osg::ApplicationUsage& usage) const;
62 protected:
63     int _keyDump;
64 };
65
66 static void dumpOut(osg::Node* node)
67 {
68     char filename[24];
69     static int count = 1;
70
71     FGRenderer *renderer = globals->get_renderer();
72
73     while (count < 1000) {
74         FILE *fp;
75         snprintf(filename, 24, "fgviewer-%03d.osg", count++);
76         if ( (fp = fopen(filename, "r")) == NULL )
77             break;
78         fclose(fp);
79     }
80
81     if (osgDB::writeNodeFile(*node, filename))
82         std::cerr << "Entire scene graph saved to \"" << filename << "\".\n";
83     else
84         std::cerr << "Failed to save to \"" << filename << "\".\n";
85 }
86
87 bool GraphDumpHandler::handle(const osgGA::GUIEventAdapter& ea,
88                               osgGA::GUIActionAdapter& aa)
89 {
90     osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
91     if (!view)
92         return false;
93     if (ea.getHandled())
94         return false;
95     switch(ea.getEventType()) {
96     case osgGA::GUIEventAdapter::KEYUP:
97         if (ea.getKey() == _keyDump) {
98             dumpOut(view->getScene()->getSceneData());
99             return true;
100         }
101         break;
102     default:
103         return false;
104     }
105 }
106
107 void GraphDumpHandler::getUsage(osg::ApplicationUsage& usage) const
108 {
109     std::ostringstream ostr;
110     ostr << char(_keyDump);
111             usage.addKeyboardMouseBinding(ostr.str(),
112                                           "Dump scene graph to file");
113 }
114
115 int
116 fgviewerMain(int argc, char** argv)
117 {
118
119     sgUserDataInit(0);
120     DummyLoadHelper dummyLoadHelper;
121     simgear::TileEntry::setModelLoadHelper(&dummyLoadHelper);
122
123     // use an ArgumentParser object to manage the program arguments.
124     osg::ArgumentParser arguments(&argc, argv);
125
126     // construct the viewer.
127     osgViewer::Viewer viewer(arguments);
128     osg::Camera* camera = viewer.getCamera();
129     osgViewer::Renderer* renderer
130         = static_cast<osgViewer::Renderer*>(camera->getRenderer());
131     for (int i = 0; i < 2; ++i) {
132         osgUtil::SceneView* sceneView = renderer->getSceneView(i);
133         sceneView->setCullVisitor(new simgear::EffectCullVisitor);
134     }
135     // Shaders expect valid fog
136     osg::StateSet* cameraSS = camera->getOrCreateStateSet();
137     osg::Fog* fog = new osg::Fog;
138     fog->setMode(osg::Fog::EXP2);
139     fog->setColor(osg::Vec4(1.0, 1.0, 1.0, 1.0));
140     fog->setDensity(.0000001);
141     cameraSS->setAttributeAndModes(fog);
142     // ... for some reason, get rid of that FIXME!
143     viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
144
145     // set up the camera manipulators.
146     osgGA::KeySwitchMatrixManipulator* keyswitchManipulator;
147     keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
148
149     osgGA::MatrixManipulator* mm = new osgGA::TrackballManipulator;
150     keyswitchManipulator->addMatrixManipulator('1', "Trackball", mm);
151     mm = new osgGA::FlightManipulator;
152     keyswitchManipulator->addMatrixManipulator('2', "Flight", mm);
153     mm = new osgGA::DriveManipulator;
154     keyswitchManipulator->addMatrixManipulator('3', "Drive", mm);
155     mm = new osgGA::TerrainManipulator;
156     keyswitchManipulator->addMatrixManipulator('4', "Terrain", mm);
157
158     viewer.setCameraManipulator(keyswitchManipulator);
159
160     // Usefull stats
161     viewer.addEventHandler(new osgViewer::HelpHandler);
162     viewer.addEventHandler(new osgViewer::StatsHandler);
163     viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
164     // Same FIXME ...
165     // viewer.addEventHandler(new osgViewer::ThreadingHandler);
166     viewer.addEventHandler(new osgViewer::LODScaleHandler);
167     viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);
168
169     viewer.addEventHandler(new GraphDumpHandler);
170
171     // Extract files to load from arguments now; this way fgInitConfig
172     // won't choke on them.
173     string_list dataFiles;
174     for (int i = arguments.argc() - 1; i >= 0; --i) {
175         if (arguments.isOption(i)) {
176             break;
177         } else {
178             dataFiles.insert(dataFiles.begin(), arguments[i]);
179             arguments.remove(i);
180         }
181     }
182
183     // A subset of full flightgear initialization.
184     // Allocate global data structures.  This needs to happen before
185     // we parse command line options
186
187     globals = new FGGlobals;
188
189     fgInitFGRoot(arguments.argc(), arguments.argv());
190     if ( !fgInitConfig(arguments.argc(), arguments.argv()) ) {
191         SG_LOG( SG_GENERAL, SG_ALERT, "Config option parsing failed ..." );
192         exit(-1);
193     }
194
195     osgDB::FilePathList filePathList
196         = osgDB::Registry::instance()->getDataFilePathList();
197     filePathList.push_back(globals->get_fg_root());
198
199     string_list path_list = globals->get_fg_scenery();
200     for (unsigned i = 0; i < path_list.size(); ++i) {
201         filePathList.push_back(path_list[i]);
202     }
203
204     globals->set_matlib( new SGMaterialLib );
205     simgear::SGModelLib::init(globals->get_fg_root());
206
207     // Initialize the material property subsystem.
208
209     SGPath mpath( globals->get_fg_root() );
210     mpath.append( "materials.xml" );
211     if ( ! globals->get_matlib()->load(globals->get_fg_root(), mpath.str(),
212             globals->get_props()) ) {
213         SG_LOG( SG_GENERAL, SG_ALERT, "Error loading material lib!" );
214         exit(-1);
215     }
216
217     globals->set_scenery( new FGScenery );
218     globals->get_scenery()->init();
219     globals->get_scenery()->bind();
220
221     // The file path list must be set in the registry.
222     osgDB::Registry::instance()->getDataFilePathList() = filePathList;
223
224     SGReaderWriterBTGOptions* btgOptions = new SGReaderWriterBTGOptions;
225     btgOptions->getDatabasePathList() = filePathList;
226     btgOptions->setMatlib(globals->get_matlib());
227     btgOptions->setUseRandomObjects(fgGetBool("/sim/rendering/random-objects", false));
228     btgOptions->setUseRandomVegetation(fgGetBool("/sim/rendering/random-vegetation", false));
229
230     // read the scene from the list of file specified command line args.
231     osg::ref_ptr<osg::Node> loadedModel;
232     loadedModel = osgDB::readNodeFiles(dataFiles, btgOptions);
233
234     // if no model has been successfully loaded report failure.
235     if (!loadedModel.valid()) {
236         std::cerr << arguments.getApplicationName()
237                   << ": No data loaded" << std::endl;
238         return EXIT_FAILURE;
239     }
240
241     // pass the loaded scene graph to the viewer.
242     viewer.setSceneData(loadedModel.get());
243
244     return viewer.run();
245 }