1999-06-18 03:42:54 +00:00
|
|
|
// main.cxx -- top level sim routines
|
1998-04-21 17:02:27 +00:00
|
|
|
//
|
2002-04-05 00:38:55 +00:00
|
|
|
// Written by Curtis Olson, started May 1997.
|
1998-04-21 17:02:27 +00:00
|
|
|
//
|
2004-11-19 22:10:41 +00:00
|
|
|
// Copyright (C) 1997 - 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
1998-04-21 17:02:27 +00:00
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful, but
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
2006-02-21 01:16:04 +00:00
|
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
1998-04-21 17:02:27 +00:00
|
|
|
//
|
|
|
|
// $Id$
|
|
|
|
|
1999-06-18 03:42:54 +00:00
|
|
|
|
1998-04-24 00:49:17 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
1998-04-21 17:02:27 +00:00
|
|
|
|
2003-08-17 09:54:41 +00:00
|
|
|
#include <simgear/compiler.h>
|
|
|
|
|
2001-12-22 23:16:43 +00:00
|
|
|
#if defined(__linux__) && defined(__i386__)
|
2001-12-22 19:10:37 +00:00
|
|
|
# include <fpu_control.h>
|
2002-01-04 20:56:28 +00:00
|
|
|
# include <signal.h>
|
2001-12-22 19:10:37 +00:00
|
|
|
#endif
|
|
|
|
|
2008-08-14 18:13:39 +00:00
|
|
|
#include <iostream>
|
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
#include <osg/Camera>
|
|
|
|
#include <osg/GraphicsContext>
|
2008-03-22 09:31:06 +00:00
|
|
|
#include <osgDB/Registry>
|
|
|
|
|
2005-03-09 21:56:00 +00:00
|
|
|
// Class references
|
2003-05-15 21:35:51 +00:00
|
|
|
#include <simgear/scene/model/modellib.hxx>
|
2004-09-20 13:21:51 +00:00
|
|
|
#include <simgear/scene/material/matlib.hxx>
|
|
|
|
#include <simgear/scene/model/animation.hxx>
|
|
|
|
#include <simgear/scene/sky/sky.hxx>
|
2008-07-31 12:04:32 +00:00
|
|
|
#include <simgear/structure/event_mgr.hxx>
|
2009-11-03 11:41:00 +00:00
|
|
|
#include <simgear/props/AtomicChangeListener.hxx>
|
2008-07-31 12:04:32 +00:00
|
|
|
#include <simgear/props/props.hxx>
|
2010-12-26 23:19:57 +00:00
|
|
|
#include <simgear/timing/sg_time.hxx>
|
2011-10-28 15:01:50 +00:00
|
|
|
#include <simgear/timing/timestamp.hxx>
|
2010-12-26 23:19:57 +00:00
|
|
|
#include <simgear/magvar/magvar.hxx>
|
2008-07-31 12:04:32 +00:00
|
|
|
#include <simgear/math/sg_random.h>
|
2010-10-23 19:37:26 +00:00
|
|
|
#include <simgear/io/raw_socket.hxx>
|
2011-06-11 22:44:07 +00:00
|
|
|
#include <simgear/scene/tsync/terrasync.hxx>
|
2008-07-31 12:04:32 +00:00
|
|
|
|
2004-09-20 13:21:51 +00:00
|
|
|
#include <Time/light.hxx>
|
2005-11-01 13:41:49 +00:00
|
|
|
#include <Aircraft/replay.hxx>
|
2010-10-29 00:18:06 +00:00
|
|
|
#include <Aircraft/controls.hxx>
|
2003-08-17 09:54:41 +00:00
|
|
|
#include <Model/panelnode.hxx>
|
|
|
|
#include <Model/acmodel.hxx>
|
|
|
|
#include <Scenery/scenery.hxx>
|
|
|
|
#include <Scenery/tilemgr.hxx>
|
2009-10-04 13:52:53 +00:00
|
|
|
#include <Sound/fg_fx.hxx>
|
2004-12-03 21:21:16 +00:00
|
|
|
#include <Sound/beacon.hxx>
|
|
|
|
#include <Sound/morse.hxx>
|
2009-09-19 18:57:04 +00:00
|
|
|
#include <Sound/fg_fx.hxx>
|
2008-05-12 10:38:04 +00:00
|
|
|
#include <ATCDCL/ATCmgr.hxx>
|
2010-07-13 20:50:44 +00:00
|
|
|
#include <Time/TimeManager.hxx>
|
2003-08-17 09:54:41 +00:00
|
|
|
#include <Environment/environment_mgr.hxx>
|
2010-06-12 15:08:04 +00:00
|
|
|
#include <Environment/ephemeris.hxx>
|
2010-12-26 23:19:57 +00:00
|
|
|
#include <GUI/gui.h>
|
2004-07-22 16:42:14 +00:00
|
|
|
#include <GUI/new_gui.hxx>
|
2005-11-01 13:41:49 +00:00
|
|
|
#include <MultiPlayer/multiplaymgr.hxx>
|
2004-09-20 13:21:51 +00:00
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
#include "CameraGroup.hxx"
|
Andy Ross:
The biggest and coolest patch adds mouse sensitivity to the 3D
cockpits, so we can finally work the radios. This ended up requiring
significant modifications outside of the 3D cockpit code. Stuff folks
will want to look at:
+ The list of all "3D" cockpits is stored statically in the
panelnode.cxx file. This is clumsy, and won't migrate well to a
multiple-aircraft feature. Really, there should be a per-model list
of 3D panels, but I couldn't find a clean place to put this. The
only handle you get back after parsing a model is a generic ssg
node, to which I obviously can't add panel-specific methods.
+ The aircraft model is parsed *very* early in the initialization
order. Earlier, in fact, than the static list of allowable command
bindings is built in fgInitCommands(). This is bad, as it means
that mouse bindings on the instruments can't work yet. I moved the
call to fgInitCommands, but someone should look carefully to see
that I picked the right place. There's a lot of initialization
code, and I got a little lost in there... :)
+ I added yet another "update" hook to the fgRenderFrame routine to
hook the updates for the 3D panels. This is only required for
"mouse press delay", and it's a fairly clumsy mechanism based on
frame rate instead of real time. There appears to be delay handling
already in place in the Input stuff, and there's a discussion going
on about different mouse behavior right now. Maybe this is a good
time to unify these two (now three) approaches?
2002-10-29 19:44:03 +00:00
|
|
|
#include "fg_commands.hxx"
|
2003-08-17 09:54:41 +00:00
|
|
|
#include "fg_io.hxx"
|
2004-09-20 13:21:51 +00:00
|
|
|
#include "renderer.hxx"
|
|
|
|
#include "splash.hxx"
|
2003-08-29 16:46:21 +00:00
|
|
|
#include "main.hxx"
|
2008-07-11 16:36:54 +00:00
|
|
|
#include "util.hxx"
|
2008-07-29 08:27:48 +00:00
|
|
|
#include "fg_init.hxx"
|
2009-08-05 14:29:32 +00:00
|
|
|
#include "fg_os.hxx"
|
2008-08-01 15:57:29 +00:00
|
|
|
#include "WindowSystemAdapter.hxx"
|
2009-09-19 18:41:55 +00:00
|
|
|
#include <Main/viewer.hxx>
|
2002-05-11 16:28:50 +00:00
|
|
|
|
2003-08-29 16:46:21 +00:00
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
using namespace flightgear;
|
|
|
|
|
2008-08-14 18:13:39 +00:00
|
|
|
using std::cerr;
|
|
|
|
|
1998-07-06 02:42:02 +00:00
|
|
|
// Specify our current idle function state. This is used to run all
|
2004-03-31 21:10:32 +00:00
|
|
|
// our initializations out of the idle callback so that we can get a
|
1998-07-06 02:42:02 +00:00
|
|
|
// splash screen up and running right away.
|
2004-09-20 13:21:51 +00:00
|
|
|
int idle_state = 0;
|
2000-03-02 13:51:31 +00:00
|
|
|
|
2002-03-12 16:30:27 +00:00
|
|
|
|
2010-01-10 11:00:52 +00:00
|
|
|
void fgInitSoundManager();
|
2009-11-30 14:24:16 +00:00
|
|
|
void fgSetNewSoundDevice(const char *);
|
|
|
|
|
2006-08-07 15:16:46 +00:00
|
|
|
// The atexit() function handler should know when the graphical subsystem
|
2004-08-24 08:40:41 +00:00
|
|
|
// is initialized.
|
|
|
|
extern int _bootstrap_OSInit;
|
|
|
|
|
1998-04-24 00:49:17 +00:00
|
|
|
// What should we do when we have nothing else to do? Let's get ready
|
|
|
|
// for the next move and update the display?
|
1998-04-21 17:02:27 +00:00
|
|
|
static void fgMainLoop( void ) {
|
2011-11-04 09:40:09 +00:00
|
|
|
|
2007-10-16 15:01:19 +00:00
|
|
|
static SGPropertyNode_ptr frame_signal
|
|
|
|
= fgGetNode("/sim/signals/frame", true);
|
2001-10-28 16:16:30 +00:00
|
|
|
|
2011-03-23 22:09:02 +00:00
|
|
|
static SGPropertyNode_ptr _statisticsFlag
|
|
|
|
= fgGetNode("/sim/timing-statistics/enabled", true);
|
|
|
|
static SGPropertyNode_ptr _statisticsInterval
|
|
|
|
= fgGetNode("/sim/timing-statistics/interval-s", true);
|
|
|
|
static SGPropertyNode_ptr _statiticsMinJitter
|
|
|
|
= fgGetNode("/sim/timing-statistics/min-jitter-ms", true);
|
|
|
|
static SGPropertyNode_ptr _statiticsMinTime
|
|
|
|
= fgGetNode("/sim/timing-statistics/min-time-ms", true);
|
|
|
|
|
2008-05-18 21:13:25 +00:00
|
|
|
frame_signal->fireValueChanged();
|
2010-07-13 20:50:44 +00:00
|
|
|
|
2011-08-11 22:09:26 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_DEBUG, "Running Main Loop");
|
|
|
|
SG_LOG( SG_GENERAL, SG_DEBUG, "======= ==== ====");
|
2010-07-13 20:50:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
// update "time"
|
|
|
|
double sim_dt, real_dt;
|
|
|
|
TimeManager* timeMgr = (TimeManager*) globals->get_subsystem("time");
|
|
|
|
// compute simulated time (allowing for pause, warp, etc) and
|
|
|
|
// real elapsed time
|
|
|
|
timeMgr->computeTimeDeltas(sim_dt, real_dt);
|
2003-09-20 11:05:12 +00:00
|
|
|
|
2000-07-05 02:39:30 +00:00
|
|
|
// update magvar model
|
2011-11-04 09:40:09 +00:00
|
|
|
globals->get_mag()->update( globals->get_aircraft_position(),
|
2006-08-07 15:16:46 +00:00
|
|
|
globals->get_time_params()->getJD() );
|
2000-07-05 02:39:30 +00:00
|
|
|
|
2002-03-01 17:39:52 +00:00
|
|
|
// Run ATC subsystem
|
2010-12-28 18:08:41 +00:00
|
|
|
globals->get_ATC_mgr()->update(sim_dt);
|
2010-06-16 16:46:41 +00:00
|
|
|
|
2010-07-13 20:50:44 +00:00
|
|
|
globals->get_subsystem_mgr()->update(sim_dt);
|
2005-08-14 12:57:12 +00:00
|
|
|
|
2009-10-05 09:12:50 +00:00
|
|
|
// Update the sound manager last so it can use the CPU while the GPU
|
|
|
|
// is processing the scenery (doubled the frame-rate for me) -EMH-
|
2008-09-05 19:46:21 +00:00
|
|
|
#ifdef ENABLE_AUDIO_SUPPORT
|
2010-01-10 11:00:52 +00:00
|
|
|
static bool smgr_init = true;
|
2010-04-10 09:37:22 +00:00
|
|
|
static SGPropertyNode *sound_working = fgGetNode("/sim/sound/working");
|
2010-01-10 11:00:52 +00:00
|
|
|
if (smgr_init == true) {
|
|
|
|
if (sound_working->getBoolValue() == true) {
|
|
|
|
fgInitSoundManager();
|
|
|
|
smgr_init = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
static SGPropertyNode *sound_enabled = fgGetNode("/sim/sound/enabled");
|
|
|
|
static SGSoundMgr *smgr = globals->get_soundmgr();
|
|
|
|
static bool smgr_enabled = true;
|
|
|
|
|
2010-04-10 09:37:22 +00:00
|
|
|
if (sound_working->getBoolValue() == false) { // request to reinit
|
|
|
|
smgr->reinit();
|
2010-04-10 09:46:27 +00:00
|
|
|
smgr->resume();
|
2010-04-10 09:37:22 +00:00
|
|
|
sound_working->setBoolValue(true);
|
|
|
|
}
|
|
|
|
|
2010-01-10 11:00:52 +00:00
|
|
|
if (smgr_enabled != sound_enabled->getBoolValue()) {
|
|
|
|
if (smgr_enabled == true) { // request to suspend
|
|
|
|
smgr->suspend();
|
|
|
|
smgr_enabled = false;
|
|
|
|
} else {
|
|
|
|
smgr->resume();
|
|
|
|
smgr_enabled = true;
|
|
|
|
}
|
2009-11-29 10:24:47 +00:00
|
|
|
}
|
|
|
|
|
2010-01-10 11:00:52 +00:00
|
|
|
if (smgr_enabled == true) {
|
|
|
|
static SGPropertyNode *volume = fgGetNode("/sim/sound/volume");
|
|
|
|
smgr->set_volume(volume->getFloatValue());
|
2010-07-13 20:50:44 +00:00
|
|
|
smgr->update(sim_dt);
|
2010-01-10 11:00:52 +00:00
|
|
|
}
|
2009-11-29 10:24:47 +00:00
|
|
|
}
|
2008-09-05 19:46:21 +00:00
|
|
|
#endif
|
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
// END Tile Manager updates
|
2010-07-13 20:50:44 +00:00
|
|
|
bool scenery_loaded = fgGetBool("sim/sceneryloaded");
|
2010-11-19 12:59:43 +00:00
|
|
|
if (!scenery_loaded)
|
|
|
|
{
|
|
|
|
if (globals->get_tile_mgr()->isSceneryLoaded()
|
|
|
|
&& fgGetBool("sim/fdm-initialized")) {
|
|
|
|
fgSetBool("sim/sceneryloaded",true);
|
2011-05-21 11:22:47 +00:00
|
|
|
fgSplashProgress("");
|
2010-11-19 12:59:43 +00:00
|
|
|
if (fgGetBool("/sim/sound/working")) {
|
|
|
|
globals->get_soundmgr()->activate();
|
|
|
|
}
|
|
|
|
globals->get_props()->tie("/sim/sound/devices/name",
|
|
|
|
SGRawValueFunctions<const char *>(0, fgSetNewSoundDevice), false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-05-22 16:28:42 +00:00
|
|
|
fgSplashProgress("loading scenery");
|
2010-11-19 12:59:43 +00:00
|
|
|
// be nice to loader threads while waiting for initial scenery, reduce to 2fps
|
2011-10-28 15:01:50 +00:00
|
|
|
SGTimeStamp::sleepForMSec(500);
|
2009-10-18 13:45:01 +00:00
|
|
|
}
|
2004-07-22 16:42:14 +00:00
|
|
|
}
|
2011-03-23 22:09:02 +00:00
|
|
|
|
|
|
|
// print timing statistics
|
|
|
|
static bool _lastStatisticsFlag = false;
|
|
|
|
if (_lastStatisticsFlag != _statisticsFlag->getBoolValue())
|
|
|
|
{
|
|
|
|
// flag has changed, update subsystem manager
|
|
|
|
_lastStatisticsFlag = _statisticsFlag->getBoolValue();
|
|
|
|
globals->get_subsystem_mgr()->collectDebugTiming(_lastStatisticsFlag);
|
|
|
|
}
|
|
|
|
if (_lastStatisticsFlag)
|
|
|
|
{
|
|
|
|
static double elapsed = 0;
|
|
|
|
elapsed += real_dt;
|
|
|
|
if (elapsed >= _statisticsInterval->getDoubleValue())
|
|
|
|
{
|
|
|
|
// print and reset timing statistics
|
|
|
|
globals->get_subsystem_mgr()->printTimingStatistics(_statiticsMinTime->getDoubleValue(),
|
|
|
|
_statiticsMinJitter->getDoubleValue());
|
|
|
|
elapsed = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-03 11:41:00 +00:00
|
|
|
simgear::AtomicChangeListener::fireChangeListeners();
|
2002-04-19 00:25:25 +00:00
|
|
|
|
2011-08-11 22:09:26 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_DEBUG, "" );
|
1998-04-21 17:02:27 +00:00
|
|
|
}
|
|
|
|
|
2010-01-10 11:00:52 +00:00
|
|
|
void fgInitSoundManager()
|
|
|
|
{
|
|
|
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
|
|
|
|
|
|
|
smgr->bind();
|
|
|
|
smgr->init(fgGetString("/sim/sound/device-name", NULL));
|
|
|
|
|
|
|
|
vector <const char*>devices = smgr->get_available_devices();
|
|
|
|
for (unsigned int i=0; i<devices.size(); i++) {
|
|
|
|
SGPropertyNode *p = fgGetNode("/sim/sound/devices/device", i, true);
|
|
|
|
p->setStringValue(devices[i]);
|
|
|
|
}
|
|
|
|
devices.clear();
|
|
|
|
}
|
|
|
|
|
2009-11-30 14:24:16 +00:00
|
|
|
void fgSetNewSoundDevice(const char *device)
|
|
|
|
{
|
|
|
|
globals->get_soundmgr()->suspend();
|
|
|
|
globals->get_soundmgr()->stop();
|
|
|
|
globals->get_soundmgr()->init(device);
|
|
|
|
globals->get_soundmgr()->resume();
|
|
|
|
}
|
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
// Operation for querying OpenGL parameters. This must be done in a
|
|
|
|
// valid OpenGL context, potentially in another thread.
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
struct GeneralInitOperation : public GraphicsContextOperation
|
|
|
|
{
|
|
|
|
GeneralInitOperation()
|
|
|
|
: GraphicsContextOperation(std::string("General init"))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
void run(osg::GraphicsContext* gc)
|
|
|
|
{
|
2010-10-01 08:33:31 +00:00
|
|
|
SGPropertyNode* simRendering = fgGetNode("/sim/rendering");
|
|
|
|
|
|
|
|
simRendering->setStringValue("gl-vendor", (char*) glGetString(GL_VENDOR));
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, glGetString(GL_VENDOR));
|
|
|
|
|
|
|
|
simRendering->setStringValue("gl-renderer", (char*) glGetString(GL_RENDERER));
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, glGetString(GL_RENDERER));
|
|
|
|
|
|
|
|
simRendering->setStringValue("gl-version", (char*) glGetString(GL_VERSION));
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, glGetString(GL_VERSION));
|
2005-05-04 21:28:42 +00:00
|
|
|
|
|
|
|
GLint tmp;
|
|
|
|
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &tmp );
|
2010-10-01 08:33:31 +00:00
|
|
|
simRendering->setIntValue("max-texture-size", tmp);
|
2005-05-04 21:28:42 +00:00
|
|
|
|
|
|
|
glGetIntegerv( GL_DEPTH_BITS, &tmp );
|
2010-10-01 08:33:31 +00:00
|
|
|
simRendering->setIntValue("depth-buffer-bits", tmp);
|
2008-08-01 15:57:29 +00:00
|
|
|
}
|
|
|
|
};
|
2010-07-29 00:07:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
osg::Node* load_panel(SGPropertyNode *n)
|
|
|
|
{
|
|
|
|
osg::Geode* geode = new osg::Geode;
|
|
|
|
geode->addDrawable(new FGPanelNode(n));
|
|
|
|
return geode;
|
|
|
|
}
|
|
|
|
|
|
|
|
SGPath resolve_path(const std::string& s)
|
|
|
|
{
|
|
|
|
return globals->resolve_maybe_aircraft_path(s);
|
|
|
|
}
|
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
}
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
// This is the top level master main function that is registered as
|
2011-05-22 16:28:42 +00:00
|
|
|
// our idle function
|
2007-04-29 09:58:37 +00:00
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
// The first few passes take care of initialization things (a couple
|
|
|
|
// per pass) and once everything has been initialized fgMainLoop from
|
|
|
|
// then on.
|
2007-04-29 09:58:37 +00:00
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
static void fgIdleFunction ( void ) {
|
|
|
|
static osg::ref_ptr<GeneralInitOperation> genOp;
|
|
|
|
if ( idle_state == 0 ) {
|
|
|
|
idle_state++;
|
|
|
|
// Pick some window on which to do queries.
|
|
|
|
// XXX Perhaps all this graphics initialization code should be
|
|
|
|
// moved to renderer.cxx?
|
|
|
|
genOp = new GeneralInitOperation;
|
|
|
|
osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
|
|
|
|
WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
|
|
|
|
osg::GraphicsContext* gc = 0;
|
|
|
|
if (guiCamera)
|
|
|
|
gc = guiCamera->getGraphicsContext();
|
|
|
|
if (gc) {
|
|
|
|
gc->add(genOp.get());
|
|
|
|
} else {
|
|
|
|
wsa->windows[0]->gc->add(genOp.get());
|
|
|
|
}
|
|
|
|
guiStartInit(gc);
|
2007-04-29 09:58:37 +00:00
|
|
|
} else if ( idle_state == 1 ) {
|
2008-08-01 15:57:29 +00:00
|
|
|
if (genOp.valid()) {
|
|
|
|
if (!genOp->isFinished())
|
|
|
|
return;
|
|
|
|
genOp = 0;
|
|
|
|
}
|
2008-05-19 21:21:03 +00:00
|
|
|
if (!guiFinishInit())
|
|
|
|
return;
|
2007-04-29 09:58:37 +00:00
|
|
|
idle_state++;
|
2011-05-22 16:28:42 +00:00
|
|
|
fgSplashProgress("loading aircraft list");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 2 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
2011-05-22 16:28:42 +00:00
|
|
|
fgSplashProgress("loading navigation data");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 3 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
|
|
|
fgInitNav();
|
|
|
|
|
2011-05-22 16:28:42 +00:00
|
|
|
fgSplashProgress("initializing scenery system");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 4 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
|
|
|
// based on the requested presets, calculate the true starting
|
|
|
|
// lon, lat
|
|
|
|
fgInitPosition();
|
2007-04-04 19:05:59 +00:00
|
|
|
fgInitTowerLocationListener();
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2010-07-13 20:50:44 +00:00
|
|
|
TimeManager* t = new TimeManager;
|
|
|
|
globals->add_subsystem("time", t, SGSubsystemMgr::INIT);
|
|
|
|
t->init(); // need to init now, not during initSubsystems
|
|
|
|
|
2005-05-04 21:28:42 +00:00
|
|
|
// Do some quick general initializations
|
|
|
|
if( !fgInitGeneral()) {
|
2006-08-07 15:16:46 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
|
|
|
"General initialization failed ..." );
|
2005-05-04 21:28:42 +00:00
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the property-based built-in commands
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
fgInitCommands();
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the material manager
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
globals->set_matlib( new SGMaterialLib );
|
2011-04-03 17:13:51 +00:00
|
|
|
simgear::SGModelLib::init(globals->get_fg_root(), globals->get_props());
|
2010-07-29 00:07:32 +00:00
|
|
|
simgear::SGModelLib::setPanelFunc(load_panel);
|
2011-05-22 16:28:42 +00:00
|
|
|
|
2005-05-04 21:28:42 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the TG scenery subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2011-06-11 22:44:07 +00:00
|
|
|
simgear::SGTerraSync* terra_sync = new simgear::SGTerraSync(globals->get_props());
|
|
|
|
globals->add_subsystem("terrasync", terra_sync);
|
2005-05-04 21:28:42 +00:00
|
|
|
globals->set_scenery( new FGScenery );
|
|
|
|
globals->get_scenery()->init();
|
|
|
|
globals->get_scenery()->bind();
|
|
|
|
globals->set_tile_mgr( new FGTileMgr );
|
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
fgSplashProgress("loading aircraft");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 5 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
2009-10-05 09:12:50 +00:00
|
|
|
|
2011-05-22 16:28:42 +00:00
|
|
|
fgSplashProgress("initializing sky elements");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 6 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
|
|
|
// Initialize the sky
|
2010-06-12 15:08:04 +00:00
|
|
|
|
|
|
|
Ephemeris* eph = new Ephemeris;
|
2010-07-13 20:50:44 +00:00
|
|
|
globals->add_subsystem("ephemeris", eph);
|
2010-06-12 15:08:04 +00:00
|
|
|
eph->init(); // FIXME - remove this once SGSky code below is also a subsystem
|
2010-06-26 19:58:45 +00:00
|
|
|
eph->bind();
|
2005-05-04 21:28:42 +00:00
|
|
|
|
|
|
|
// TODO: move to environment mgr
|
|
|
|
thesky = new SGSky;
|
|
|
|
SGPath texture_path(globals->get_fg_root());
|
|
|
|
texture_path.append("Textures");
|
|
|
|
texture_path.append("Sky");
|
|
|
|
for (int i = 0; i < FGEnvironmentMgr::MAX_CLOUD_LAYERS; i++) {
|
|
|
|
SGCloudLayer * layer = new SGCloudLayer(texture_path.str());
|
|
|
|
thesky->add_cloud_layer(layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
SGPath sky_tex_path( globals->get_fg_root() );
|
|
|
|
sky_tex_path.append( "Textures" );
|
|
|
|
sky_tex_path.append( "Sky" );
|
|
|
|
thesky->texture_path( sky_tex_path.str() );
|
|
|
|
|
|
|
|
// The sun and moon diameters are scaled down numbers of the
|
2006-08-07 15:16:46 +00:00
|
|
|
// actual diameters. This was needed to fit both the sun and the
|
2005-05-04 21:28:42 +00:00
|
|
|
// moon within the distance to the far clip plane.
|
|
|
|
// Moon diameter: 3,476 kilometers
|
|
|
|
// Sun diameter: 1,390,000 kilometers
|
|
|
|
thesky->build( 80000.0, 80000.0,
|
|
|
|
463.3, 361.8,
|
2009-03-17 12:26:27 +00:00
|
|
|
*globals->get_ephem(),
|
2006-08-07 15:16:46 +00:00
|
|
|
fgGetNode("/environment", true));
|
2005-05-04 21:28:42 +00:00
|
|
|
|
|
|
|
// Initialize MagVar model
|
|
|
|
SGMagVar *magvar = new SGMagVar();
|
|
|
|
globals->set_mag( magvar );
|
|
|
|
|
|
|
|
|
2011-11-04 09:40:09 +00:00
|
|
|
// kludge to initialize mag compass
|
|
|
|
// (should only be done for in-flight
|
|
|
|
// startup)
|
2005-05-04 21:28:42 +00:00
|
|
|
// update magvar model
|
2011-11-04 09:40:09 +00:00
|
|
|
globals->get_mag()->update( globals->get_aircraft_position(),
|
2005-05-04 21:28:42 +00:00
|
|
|
globals->get_time_params()->getJD() );
|
|
|
|
double var = globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
|
|
|
|
fgSetDouble("/instrumentation/heading-indicator/offset-deg", -var);
|
2006-06-24 03:42:30 +00:00
|
|
|
fgSetDouble("/instrumentation/heading-indicator-fg/offset-deg", -var);
|
|
|
|
|
2005-05-04 21:28:42 +00:00
|
|
|
|
|
|
|
// airport = new ssgBranch;
|
|
|
|
// airport->setName( "Airport Lighting" );
|
|
|
|
// lighting->addKid( airport );
|
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
fgSplashProgress("initializing subsystems");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 7 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
2003-04-15 14:10:47 +00:00
|
|
|
// Initialize audio support
|
2001-07-11 06:01:55 +00:00
|
|
|
#ifdef ENABLE_AUDIO_SUPPORT
|
|
|
|
|
2003-04-15 14:10:47 +00:00
|
|
|
// Start the intro music
|
|
|
|
if ( fgGetBool("/sim/startup/intro-music") ) {
|
|
|
|
SGPath mp3file( globals->get_fg_root() );
|
|
|
|
mp3file.append( "Sounds/intro.mp3" );
|
1999-04-27 19:27:45 +00:00
|
|
|
|
2006-08-07 15:16:46 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO,
|
2003-04-15 14:10:47 +00:00
|
|
|
"Starting intro music: " << mp3file.str() );
|
2001-07-11 06:01:55 +00:00
|
|
|
|
2009-10-04 13:52:53 +00:00
|
|
|
# if defined( __CYGWIN__ )
|
2003-04-15 14:10:47 +00:00
|
|
|
string command = "start /m `cygpath -w " + mp3file.str() + "`";
|
2010-01-23 22:26:30 +00:00
|
|
|
# elif defined( _WIN32 )
|
2003-04-15 14:10:47 +00:00
|
|
|
string command = "start /m " + mp3file.str();
|
2009-10-04 13:52:53 +00:00
|
|
|
# else
|
2003-04-15 14:10:47 +00:00
|
|
|
string command = "mpg123 " + mp3file.str() + "> /dev/null 2>&1";
|
2009-10-04 13:52:53 +00:00
|
|
|
# endif
|
2002-02-05 05:04:02 +00:00
|
|
|
|
2003-04-15 14:10:47 +00:00
|
|
|
system ( command.c_str() );
|
|
|
|
}
|
1998-07-06 02:42:02 +00:00
|
|
|
#endif
|
2003-04-15 14:10:47 +00:00
|
|
|
// This is the top level init routine which calls all the
|
|
|
|
// other subsystem initialization routines. If you are adding
|
2006-08-07 15:16:46 +00:00
|
|
|
// a subsystem to flightgear, its initialization call should be
|
2003-04-15 14:10:47 +00:00
|
|
|
// located in this routine.
|
|
|
|
if( !fgInitSubsystems()) {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
2006-08-07 15:16:46 +00:00
|
|
|
"Subsystem initialization failed ..." );
|
2003-04-15 14:10:47 +00:00
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
2010-11-10 21:19:25 +00:00
|
|
|
// Torsten Dreyer:
|
|
|
|
// ugly hack for automatic runway selection on startup based on
|
|
|
|
// metar data. Makes startup.nas obsolete and guarantees the same
|
|
|
|
// runway selection as for AI traffic. However, this code belongs to
|
|
|
|
// somewhere(?) else - if I only new where...
|
|
|
|
if( true == fgGetBool( "/environment/metar/valid" ) ) {
|
2011-09-17 17:26:23 +00:00
|
|
|
SG_LOG(SG_ENVIRONMENT, SG_INFO,
|
|
|
|
"Using METAR for runway selection: '" << fgGetString("/environment/metar/data") << "'" );
|
2010-11-10 21:19:25 +00:00
|
|
|
// the realwx_ctrl fetches metar in the foreground on init,
|
|
|
|
// If it was able to fetch a metar or one was given on the commandline,
|
|
|
|
// the valid flag is set here, otherwise it is false
|
|
|
|
double hdg = fgGetDouble( "/environment/metar/base-wind-dir-deg", 9999.0 );
|
|
|
|
string apt = fgGetString( "/sim/startup/options/airport" );
|
|
|
|
string rwy = fgGetString( "/sim/startup/options/runway" );
|
|
|
|
double strthdg = fgGetDouble( "/sim/startup/options/heading-deg", 9999.0 );
|
2010-11-10 22:28:07 +00:00
|
|
|
string parkpos = fgGetString( "/sim/presets/parkpos" );
|
2010-11-10 21:19:25 +00:00
|
|
|
bool onground = fgGetBool( "/sim/presets/onground", false );
|
|
|
|
// don't check for wind-speed < 1kt, this belongs to the runway-selection code
|
|
|
|
// the other logic is taken from former startup.nas
|
2010-11-10 22:28:07 +00:00
|
|
|
if( hdg < 360.0 && apt.length() > 0 && strthdg > 360.0 && rwy.length() == 0 && onground && parkpos.length() == 0 ) {
|
2010-11-10 21:19:25 +00:00
|
|
|
extern bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg );
|
|
|
|
fgSetPosFromAirportIDandHdg( apt, hdg );
|
|
|
|
}
|
2011-09-17 17:26:23 +00:00
|
|
|
} else {
|
|
|
|
SG_LOG(SG_ENVIRONMENT, SG_INFO,
|
|
|
|
"No METAR available to pick active runway" );
|
2010-11-10 21:19:25 +00:00
|
|
|
}
|
2011-05-22 16:28:42 +00:00
|
|
|
|
|
|
|
fgSplashProgress("initializing graphics engine");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 8 ) {
|
|
|
|
idle_state = 1000;
|
2010-07-13 20:50:44 +00:00
|
|
|
|
2003-04-15 14:10:47 +00:00
|
|
|
// setup OpenGL view parameters
|
2011-05-22 16:28:42 +00:00
|
|
|
globals->get_renderer()->setupView();
|
1998-07-06 02:42:02 +00:00
|
|
|
|
2004-09-20 13:21:51 +00:00
|
|
|
globals->get_renderer()->resize( fgGetInt("/sim/startup/xsize"),
|
|
|
|
fgGetInt("/sim/startup/ysize") );
|
2003-09-17 10:02:36 +00:00
|
|
|
|
2009-10-24 09:22:20 +00:00
|
|
|
int session = fgGetInt("/sim/session",0);
|
|
|
|
session++;
|
|
|
|
fgSetInt("/sim/session",session);
|
2005-05-04 21:28:42 +00:00
|
|
|
}
|
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
if ( idle_state == 1000 ) {
|
2003-04-15 14:10:47 +00:00
|
|
|
// We've finished all our initialization steps, from now on we
|
|
|
|
// run the main loop.
|
2005-05-06 09:08:44 +00:00
|
|
|
fgSetBool("sim/sceneryloaded", false);
|
2005-05-04 21:28:42 +00:00
|
|
|
fgRegisterIdleHandler( fgMainLoop );
|
1998-07-06 02:42:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-10 11:46:03 +00:00
|
|
|
static void upper_case_property(const char *name)
|
|
|
|
{
|
2009-07-17 12:54:12 +00:00
|
|
|
using namespace simgear;
|
2006-03-10 11:46:03 +00:00
|
|
|
SGPropertyNode *p = fgGetNode(name, false);
|
|
|
|
if (!p) {
|
|
|
|
p = fgGetNode(name, true);
|
|
|
|
p->setStringValue("");
|
|
|
|
} else {
|
2009-07-17 12:54:12 +00:00
|
|
|
props::Type t = p->getType();
|
|
|
|
if (t == props::NONE || t == props::UNSPECIFIED)
|
2006-03-10 11:46:03 +00:00
|
|
|
p->setStringValue("");
|
|
|
|
else
|
2009-07-17 12:54:12 +00:00
|
|
|
assert(t == props::STRING);
|
2006-03-10 11:46:03 +00:00
|
|
|
}
|
|
|
|
p->addChangeListener(new FGMakeUpperCase);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-16 20:17:11 +00:00
|
|
|
// Main top level initialization
|
2010-09-29 20:04:11 +00:00
|
|
|
int fgMainInit( int argc, char **argv ) {
|
2001-10-29 04:39:54 +00:00
|
|
|
|
1998-11-16 13:59:58 +00:00
|
|
|
// set default log levels
|
2003-11-24 17:46:38 +00:00
|
|
|
sglog().setLogLevels( SG_ALL, SG_ALERT );
|
1998-11-16 13:59:58 +00:00
|
|
|
|
2001-01-11 05:04:17 +00:00
|
|
|
string version;
|
|
|
|
#ifdef FLIGHTGEAR_VERSION
|
|
|
|
version = FLIGHTGEAR_VERSION;
|
|
|
|
#else
|
|
|
|
version = "unknown version";
|
|
|
|
#endif
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "FlightGear: Version "
|
2003-04-15 14:10:47 +00:00
|
|
|
<< version );
|
2011-10-17 16:41:59 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "Built with " << SG_COMPILER_STR << std::endl );
|
1998-11-20 01:02:35 +00:00
|
|
|
|
2000-10-19 23:09:33 +00:00
|
|
|
// Allocate global data structures. This needs to happen before
|
|
|
|
// we parse command line options
|
2001-01-12 15:37:40 +00:00
|
|
|
|
2000-10-19 21:24:43 +00:00
|
|
|
globals = new FGGlobals;
|
|
|
|
|
2006-08-07 15:16:46 +00:00
|
|
|
// seed the random number generator
|
2001-01-13 22:06:39 +00:00
|
|
|
sg_srandom_time();
|
|
|
|
|
2001-07-22 19:51:16 +00:00
|
|
|
FGControls *controls = new FGControls;
|
|
|
|
globals->set_controls( controls );
|
|
|
|
|
2001-01-26 00:21:36 +00:00
|
|
|
string_list *col = new string_list;
|
|
|
|
globals->set_channel_options_list( col );
|
|
|
|
|
2008-07-11 16:36:54 +00:00
|
|
|
fgValidatePath("", false); // initialize static variables
|
2006-03-10 11:46:03 +00:00
|
|
|
upper_case_property("/sim/presets/airport-id");
|
|
|
|
upper_case_property("/sim/presets/runway");
|
|
|
|
upper_case_property("/sim/tower/airport-id");
|
2008-06-06 07:49:41 +00:00
|
|
|
upper_case_property("/autopilot/route-manager/input");
|
2006-03-10 11:46:03 +00:00
|
|
|
|
2002-11-16 20:17:11 +00:00
|
|
|
// Load the configuration parameters. (Command line options
|
2006-08-07 15:16:46 +00:00
|
|
|
// override config file options. Config file options override
|
2002-11-16 20:17:11 +00:00
|
|
|
// defaults.)
|
1999-06-18 03:42:54 +00:00
|
|
|
if ( !fgInitConfig(argc, argv) ) {
|
2011-10-16 17:35:40 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Config option parsing failed ..." );
|
|
|
|
exit(-1);
|
1998-04-24 00:49:17 +00:00
|
|
|
}
|
1999-06-18 03:42:54 +00:00
|
|
|
|
1998-08-20 15:10:33 +00:00
|
|
|
// Initialize the Window/Graphics environment.
|
2004-03-31 21:10:32 +00:00
|
|
|
fgOSInit(&argc, argv);
|
2004-08-24 08:40:41 +00:00
|
|
|
_bootstrap_OSInit++;
|
1998-08-20 15:10:33 +00:00
|
|
|
|
2004-12-20 08:36:56 +00:00
|
|
|
fgRegisterIdleHandler( &fgIdleFunction );
|
2004-03-31 21:10:32 +00:00
|
|
|
|
2010-10-23 19:37:26 +00:00
|
|
|
// Initialize sockets (WinSock needs this)
|
|
|
|
simgear::Socket::initSockets();
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2004-03-31 21:10:32 +00:00
|
|
|
// Clouds3D requires an alpha channel
|
2010-07-01 18:51:05 +00:00
|
|
|
fgOSOpenWindow(true /* request stencil buffer */);
|
2004-03-31 21:10:32 +00:00
|
|
|
|
2005-05-04 21:28:42 +00:00
|
|
|
// Initialize the splash screen right away
|
2005-05-08 14:32:56 +00:00
|
|
|
fntInit();
|
2007-05-03 18:12:29 +00:00
|
|
|
fgSplashInit();
|
2004-05-20 13:27:40 +00:00
|
|
|
|
2004-10-17 17:29:34 +00:00
|
|
|
// pass control off to the master event handler
|
2010-09-29 20:04:11 +00:00
|
|
|
int result = fgOSMainLoop();
|
|
|
|
|
|
|
|
// clean up here; ensure we null globals to avoid
|
|
|
|
// confusing the atexit() handler
|
|
|
|
delete globals;
|
|
|
|
globals = NULL;
|
|
|
|
|
|
|
|
return result;
|
1998-04-21 17:02:27 +00:00
|
|
|
}
|