FlightGear next
fgviewer.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include <iostream>
6#include <cstdlib>
7
8#include <osg/ArgumentParser>
9#include <osg/Fog>
10#include <osgDB/ReadFile>
11#include <osgDB/Registry>
12#include <osgDB/WriteFile>
13#include <osgViewer/Renderer>
14#include <osgViewer/Viewer>
15#include <osgViewer/ViewerEventHandlers>
16#include <osgGA/KeySwitchMatrixManipulator>
17#include <osgGA/TrackballManipulator>
18#include <osgGA/FlightManipulator>
19#include <osgGA/DriveManipulator>
20#include <osgGA/TerrainManipulator>
21#include <osgGA/StateSetManipulator>
22
23#include <simgear/props/props.hxx>
24#include <simgear/props/props_io.hxx>
25#include <simgear/misc/sg_path.hxx>
26#include <simgear/scene/material/EffectCullVisitor.hxx>
27#include <simgear/scene/material/matlib.hxx>
28#include <simgear/scene/util/SGReaderWriterOptions.hxx>
29#include <simgear/scene/tgdb/userdata.hxx>
30#include <simgear/scene/model/ModelRegistry.hxx>
31#include <simgear/scene/model/modellib.hxx>
32#include <simgear/structure/exception.hxx>
33
34#include <Scenery/scenery.hxx>
35
37#include <Viewer/renderer.hxx>
38
39#include <Main/fg_props.hxx>
40#include <Main/globals.hxx>
41#include <Main/options.hxx>
42#include <Main/fg_init.hxx>
43
44class GraphDumpHandler : public osgGA::GUIEventHandler
45{
46public:
48 void setKeyDump(int key) { _keyDump = key; }
49 int getKeyDump() const { return _keyDump; }
50 bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
51
53 virtual void getUsage(osg::ApplicationUsage& usage) const;
54protected:
56};
57
58static void dumpOut(osg::Node* node)
59{
60 char filename[24];
61 static short count = 1;
62
63 while (count < 1000) {
64 FILE *fp;
65 snprintf(filename, 24, "fgviewer-%03d.osg", count++);
66 if ( (fp = fopen(filename, "r")) == NULL )
67 break;
68 fclose(fp);
69 }
70
71 if (osgDB::writeNodeFile(*node, filename))
72 std::cerr << "Entire scene graph saved to \"" << filename << "\".\n";
73 else
74 std::cerr << "Failed to save to \"" << filename << "\".\n";
75}
76
77bool GraphDumpHandler::handle(const osgGA::GUIEventAdapter& ea,
78 osgGA::GUIActionAdapter& aa)
79{
80 osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
81 if (!view)
82 return false;
83 if (ea.getHandled())
84 return false;
85 switch(ea.getEventType()) {
86 case osgGA::GUIEventAdapter::KEYUP:
87 if (ea.getKey() == _keyDump) {
88 dumpOut(view->getScene()->getSceneData());
89 return true;
90 }
91 break;
92 default:
93 return false;
94 }
95 return false;
96}
97
98void GraphDumpHandler::getUsage(osg::ApplicationUsage& usage) const
99{
100 std::ostringstream ostr;
101 ostr << char(_keyDump);
102 usage.addKeyboardMouseBinding(ostr.str(),
103 "Dump scene graph to file");
104}
105
106int
107fgviewerMain(int argc, char** argv)
108{
109
110 sgUserDataInit(0);
111
112 // use an ArgumentParser object to manage the program arguments.
113 osg::ArgumentParser arguments(&argc, argv);
114
115 // construct the viewer.
116 FGRenderer* fgrenderer = new FGRenderer();
117 osgViewer::Viewer* viewer = new osgViewer::Viewer(arguments);
118 fgrenderer->setView(viewer);
119 osg::Camera* camera = viewer->getCamera();
120 osgViewer::Renderer* renderer
121 = static_cast<osgViewer::Renderer*>(camera->getRenderer());
122 for (int i = 0; i < 2; ++i) {
123 osgUtil::SceneView* sceneView = renderer->getSceneView(i);
124 sceneView->setCullVisitor(new simgear::EffectCullVisitor);
125 }
126 // Shaders expect valid fog
127 osg::StateSet* cameraSS = camera->getOrCreateStateSet();
128 osg::Fog* fog = new osg::Fog;
129 fog->setMode(osg::Fog::EXP2);
130 fog->setColor(osg::Vec4(1.0, 1.0, 1.0, 1.0));
131 fog->setDensity(.0000001);
132 cameraSS->setAttributeAndModes(fog);
133 // ... for some reason, get rid of that FIXME!
134 viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
135
136 // set up the camera manipulators.
137 osgGA::KeySwitchMatrixManipulator* keyswitchManipulator;
138 keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
139
140 keyswitchManipulator->addMatrixManipulator('1', "Trackball",
141 new osgGA::TrackballManipulator);
142 keyswitchManipulator->addMatrixManipulator('2', "Flight",
143 new osgGA::FlightManipulator);
144 keyswitchManipulator->addMatrixManipulator('3', "Drive",
145 new osgGA::DriveManipulator);
146 keyswitchManipulator->addMatrixManipulator('4', "Terrain",
147 new osgGA::TerrainManipulator);
148 viewer->setCameraManipulator(keyswitchManipulator);
149
150 // Usefull stats
151 viewer->addEventHandler(new osgViewer::HelpHandler);
152 viewer->addEventHandler(new osgViewer::StatsHandler);
153 viewer->addEventHandler( new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()) );
154 // Same FIXME ...
155 // viewer->addEventHandler(new osgViewer::ThreadingHandler);
156 viewer->addEventHandler(new osgViewer::LODScaleHandler);
157 viewer->addEventHandler(new osgViewer::ScreenCaptureHandler);
158
159 viewer->addEventHandler(new GraphDumpHandler);
160
161 // Extract files to load from arguments now; this way fgInitConfig
162 // won't choke on them.
163 string_list dataFiles;
164 for (int i = arguments.argc() - 1; i >= 0; --i) {
165 if (arguments.isOption(i)) {
166 break;
167 } else {
168 dataFiles.insert(dataFiles.begin(), arguments[i]);
169 arguments.remove(i);
170 }
171 }
172
173 // A subset of full flightgear initialization.
174 // Allocate global data structures. This needs to happen before
175 // we parse command line options
176 globals = new FGGlobals;
177 globals->set_renderer(fgrenderer);
178
179 SGPath dataPath = fgHomePath();
180 globals->set_fg_home(dataPath);
181
182 std::string s;
183 if (arguments.read("--fg-scenery", s)) {
184 globals->append_fg_scenery(SGPath::fromLocal8Bit(s.c_str()));
185 }
186 if (std::getenv("FG_SCENERY")) {
187 globals->append_fg_scenery(SGPath::fromEnv("FG_SCENERY"));
188 }
189
190 int configResult = fgInitConfig(arguments.argc(), arguments.argv(), false);
191 if (configResult == flightgear::FG_OPTIONS_ERROR) {
192 return EXIT_FAILURE;
193 } else if (configResult == flightgear::FG_OPTIONS_EXIT) {
194 return EXIT_SUCCESS;
195 }
196
197 osgDB::FilePathList filePathList
198 = osgDB::Registry::instance()->getDataFilePathList();
199 filePathList.push_back(globals->get_fg_root().local8BitStr());
200
201 const PathList& path_list = globals->get_fg_scenery();
202 for (unsigned i = 0; i < path_list.size(); ++i) {
203 filePathList.push_back(path_list[i].local8BitStr());
204 }
205
206 globals->set_matlib( new SGMaterialLib );
207 simgear::SGModelLib::init(globals->get_fg_root().local8BitStr(), globals->get_props());
208
209 // Initialize the material property subsystem.
210
211 SGPath mpath( globals->get_fg_root() );
212 mpath.append( fgGetString("/sim/rendering/materials-file") );
213 if ( ! globals->get_matlib()->load(globals->get_fg_root().local8BitStr(),
214 mpath.local8BitStr(),
215 globals->get_props()) ) {
216 throw sg_io_exception("Error loading materials file", mpath);
217 }
218
219 // The file path list must be set in the registry.
220 osgDB::Registry::instance()->getDataFilePathList() = filePathList;
221
222 simgear::SGReaderWriterOptions* options = new simgear::SGReaderWriterOptions;
223 options->getDatabasePathList() = filePathList;
224 options->setMaterialLib(globals->get_matlib());
225 options->setPropertyNode(globals->get_props());
226 options->setPluginStringData("SimGear::PREVIEW", "ON");
227
228 // Now init the renderer, as we've got all the options, globals etc.
229 fgrenderer->init();
230
231 auto scenery = globals->get_subsystem_mgr()->add<FGScenery>();
232 scenery->init();
233 scenery->bind();
234
237 cache->updateListsOfDatFiles();
238 if (cache->isRebuildRequired()) {
240 SGTimeStamp::sleepForMSec(1000);
241 std::cerr << "." << std::flush;
242 }
243 }
244 }
245
246 // read the scene from the list of file specified command line args.
247 osg::ref_ptr<osg::Node> loadedModel;
248 loadedModel = osgDB::readNodeFiles(dataFiles, options);
249
250 // if no model has been successfully loaded report failure.
251 if (!loadedModel.valid()) {
252 std::cerr << arguments.getApplicationName()
253 << ": No data loaded" << std::endl;
254 return EXIT_FAILURE;
255 }
256
257 // pass the loaded scene graph to the viewer->
258 viewer->setSceneData(loadedModel.get());
259
260 int result = viewer->run();
261
262 // clear cache now, since it contains SimGear objects. Otherwise SG_LOG
263 // calls during shutdown will cause crashes.
264 osgDB::Registry::instance()->clearObjectCache();
265
266 return result;
267}
bool options(int, char **)
Definition JSBSim.cpp:568
#define i(x)
Bucket for subsystem pointers representing the sim's state.
Definition globals.hxx:79
void setView(osgViewer::View *view)
Definition renderer.cxx:827
void init()
Initialize the renderer.
Definition renderer.cxx:233
void init() override
Definition scenery.cxx:406
virtual void getUsage(osg::ApplicationUsage &usage) const
Get the keyboard and mouse usage of this manipulator.
Definition fgviewer.cxx:98
bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
Definition fgviewer.cxx:77
void setKeyDump(int key)
Definition fgviewer.cxx:48
int getKeyDump() const
Definition fgviewer.cxx:49
static NavDataCache * createInstance()
static NavDataCache * instance()
bool isRebuildRequired()
predicate - check if the cache needs to be rebuilt.
RebuildPhase rebuild()
run the cache rebuild - returns the current phase or 'done'
int fgInitConfig(int argc, char **argv, bool reinit)
Definition fg_init.cxx:688
SGPath fgHomePath()
Definition fg_init.cxx:524
std::string fgGetString(const char *name, const char *defaultValue)
Get a string value for a property.
Definition fg_props.cxx:556
static void dumpOut(osg::Node *node)
Definition fgviewer.cxx:58
int fgviewerMain(int argc, char **argv)
Definition fgviewer.cxx:107
FGGlobals * globals
Definition globals.cxx:142
std::vector< SGPath > PathList
Definition globals.hxx:37
std::vector< std::string > string_list
Definition globals.hxx:36
@ FG_OPTIONS_EXIT
Definition options.hxx:56
@ FG_OPTIONS_ERROR
Definition options.hxx:55
int usage()