// // fg_init.cxx -- Flight Gear top level initialization routines // // Written by Curtis Olson, started August 1997. // // Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com // // 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 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // // $Id$ #ifdef HAVE_CONFIG_H # include <config.h> #endif // For BC 5.01 this must be included before OpenGL includes. #ifdef FG_MATH_EXCEPTION_CLASH # include <math.h> #endif #include <GL/glut.h> #include <XGL/xgl.h> #include <stdio.h> #include <stdlib.h> // work around a stdc++ lib bug in some versions of linux, but doesn't // seem to hurt to have this here for all versions of Linux. #ifdef linux # define _G_NO_EXTERN_TEMPLATES #endif #include <Include/compiler.h> #include STL_STRING #include <Debug/logstream.hxx> #include <Aircraft/aircraft.hxx> #include <Airports/simple.hxx> #include <Astro/sky.hxx> #include <Astro/stars.hxx> #include <Astro/solarsystem.hxx> #include <Autopilot/autopilot.hxx> #include <Cockpit/cockpit.hxx> #include <Include/fg_constants.h> #include <Include/general.hxx> #include <Joystick/joystick.hxx> #include <Math/fg_geodesy.hxx> #include <Math/point3d.hxx> #include <Math/polar3d.hxx> #include <Scenery/scenery.hxx> #include <Scenery/tilemgr.hxx> #include <Time/event.hxx> #include <Time/fg_time.hxx> #include <Time/light.hxx> #include <Time/sunpos.hxx> #include <Time/moonpos.hxx> #include <Weather/weather.hxx> #include "fg_init.hxx" #include "options.hxx" #include "views.hxx" #include "fg_serial.hxx" #if defined(FX) && defined(XMESA) #include <GL/xmesa.h> #endif FG_USING_STD(string); extern const char *default_root; // Set initial position and orientation int fgInitPosition( void ) { string id; FGInterface *f; f = current_aircraft.fdm_state; id = current_options.get_airport_id(); if ( id.length() ) { // set initial position from airport id fgAIRPORTS airports; fgAIRPORT a; FG_LOG( FG_GENERAL, FG_INFO, "Attempting to set starting position from airport code " << id ); airports.load("apt_simple"); if ( ! airports.search( id, &a ) ) { FG_LOG( FG_GENERAL, FG_ALERT, "Failed to find " << id << " in database." ); exit(-1); } else { f->set_Longitude( a.longitude * DEG_TO_RAD ); f->set_Latitude( a.latitude * DEG_TO_RAD ); } } else { // set initial position from default or command line coordinates f->set_Longitude( current_options.get_lon() * DEG_TO_RAD ); f->set_Latitude( current_options.get_lat() * DEG_TO_RAD ); } FG_LOG( FG_GENERAL, FG_INFO, "starting altitude is = " << current_options.get_altitude() ); f->set_Altitude( current_options.get_altitude() * METER_TO_FEET ); fgFDMSetGroundElevation( current_options.get_flight_model(), (f->get_Altitude() - 3.758099) * FEET_TO_METER ); FG_LOG( FG_GENERAL, FG_INFO, "Initial position is: (" << (f->get_Longitude() * RAD_TO_DEG) << ", " << (f->get_Latitude() * RAD_TO_DEG) << ", " << (f->get_Altitude() * FEET_TO_METER) << ")" ); return(1); } // General house keeping initializations int fgInitGeneral( void ) { string root; char *mesa_win_state; FG_LOG( FG_GENERAL, FG_INFO, "General Initialization" ); FG_LOG( FG_GENERAL, FG_INFO, "======= ==============" ); root = current_options.get_fg_root(); if ( ! root.length() ) { // No root path set? Then bail ... FG_LOG( FG_GENERAL, FG_ALERT, "Cannot continue without environment variable FG_ROOT" << "being defined." ); exit(-1); } FG_LOG( FG_GENERAL, FG_INFO, "FG_ROOT = " << root << endl ); #if defined(FX) && defined(XMESA) // initialize full screen flag global_fullscreen = false; if ( strstr ( general.get_glRenderer(), "Glide" ) ) { // Test for the MESA_GLX_FX env variable if ( (mesa_win_state = getenv( "MESA_GLX_FX" )) != NULL) { // test if we are fullscreen mesa/glide if ( (mesa_win_state[0] == 'f') || (mesa_win_state[0] == 'F') ) { global_fullscreen = true; } } } #endif return 1; } // This is the top level init routine which calls all the other // initialization routines. If you are adding a subsystem to flight // gear, its initialization call should located in this routine. // Returns non-zero if a problem encountered. int fgInitSubsystems( void ) { FGTime::cur_time_params = new FGTime(); FGInterface *f; // assigned later fgLIGHT *l = &cur_light_params; FGTime *t = FGTime::cur_time_params; FGView *v = ¤t_view; FG_LOG( FG_GENERAL, FG_INFO, "Initialize Subsystems"); FG_LOG( FG_GENERAL, FG_INFO, "========== =========="); // allocates structures so must happen before any of the flight // model or control parameters are set fgAircraftInit(); // In the future this might not be the case. f = current_aircraft.fdm_state; // set the initial position fgInitPosition(); // Initialize the Scenery Management subsystem if ( fgSceneryInit() ) { // Scenery initialized ok. } else { FG_LOG( FG_GENERAL, FG_ALERT, "Error in Scenery initialization!" ); exit(-1); } if( fgTileMgrInit() ) { // Load the local scenery data fgTileMgrUpdate(); } else { FG_LOG( FG_GENERAL, FG_ALERT, "Error in Tile Manager initialization!" ); exit(-1); } FG_LOG( FG_GENERAL, FG_DEBUG, "Current terrain elevation after tile mgr init " << scenery.cur_elev ); // Calculate ground elevation at starting point (we didn't have // tmp_abs_view_pos calculated when fgTileMgrUpdate() was called above // // calculalate a cartesian point somewhere along the line between // the center of the earth and our view position. Doesn't have to // be the exact elevation (this is good because we don't know it // yet :-) // now handled inside of the fgTileMgrUpdate() /* geod_pos = Point3D( f->get_Longitude(), f->get_Latitude(), 0.0); tmp_abs_view_pos = fgGeodToCart(geod_pos); FG_LOG( FG_GENERAL, FG_DEBUG, "Initial abs_view_pos = " << tmp_abs_view_pos ); scenery.cur_elev = fgTileMgrCurElev( f->get_Longitude(), f->get_Latitude(), tmp_abs_view_pos ); FG_LOG( FG_GENERAL, FG_DEBUG, "Altitude after update " << scenery.cur_elev ); */ fgFDMSetGroundElevation( current_options.get_flight_model(), scenery.cur_elev ); // Reset our altitude if we are below ground FG_LOG( FG_GENERAL, FG_DEBUG, "Current altitude = " << f->get_Altitude() ); FG_LOG( FG_GENERAL, FG_DEBUG, "Current runway altitude = " << f->get_Runway_altitude() ); if ( f->get_Altitude() < f->get_Runway_altitude() + 3.758099) { f->set_Altitude( f->get_Runway_altitude() + 3.758099 ); } FG_LOG( FG_GENERAL, FG_INFO, "Updated position (after elevation adj): (" << (f->get_Latitude() * RAD_TO_DEG) << ", " << (f->get_Longitude() * RAD_TO_DEG) << ", " << (f->get_Altitude() * FEET_TO_METER) << ")" ); // We need to calculate a few more values here that would normally // be calculated by the FDM so that the v->UpdateViewMath() // routine doesn't get hosed. double sea_level_radius_meters; double lat_geoc; // Set the FG variables first fgGeodToGeoc( f->get_Latitude(), f->get_Altitude(), &sea_level_radius_meters, &lat_geoc); f->set_Geocentric_Position( lat_geoc, f->get_Longitude(), f->get_Altitude() + (sea_level_radius_meters * METER_TO_FEET) ); f->set_Sea_level_radius( sea_level_radius_meters * METER_TO_FEET ); f->set_sin_cos_longitude(f->get_Longitude()); f->set_sin_cos_latitude(f->get_Latitude()); f->set_sin_lat_geocentric(sin(lat_geoc)); f->set_cos_lat_geocentric(cos(lat_geoc)); // The following section sets up the flight model EOM parameters // and should really be read in from one or more files. // Initial Velocity f->set_Velocities_Local( 0.0, 0.0, 0.0 ); // Initial Orientation f->set_Euler_Angles( current_options.get_roll() * DEG_TO_RAD, current_options.get_pitch() * DEG_TO_RAD, current_options.get_heading() * DEG_TO_RAD ); // Initial Angular Body rates f->set_Omega_Body( 7.206685E-05, 0.0, 9.492658E-05 ); f->set_Earth_position_angle( 0.0 ); // Mass properties and geometry values f->set_Inertias( 8.547270E+01, 1.048000E+03, 3.000000E+03, 3.530000E+03, 0.000000E+00 ); // CG position w.r.t. ref. point f->set_CG_Position( 0.0, 0.0, 0.0 ); // Initialize the event manager global_events.Init(); // Output event stats every 60 seconds global_events.Register( "fgEVENT_MGR::PrintStats()", fgMethodCallback<fgEVENT_MGR>( &global_events, &fgEVENT_MGR::PrintStats), fgEVENT::FG_EVENT_READY, 60000 ); // Initialize the time dependent variables t->init(); t->update(f); // Initialize view parameters FG_LOG( FG_GENERAL, FG_DEBUG, "Before v->init()"); v->Init(); FG_LOG( FG_GENERAL, FG_DEBUG, "After v->init()"); v->UpdateViewMath(f); FG_LOG( FG_GENERAL, FG_DEBUG, " abs_view_pos = " << v->get_abs_view_pos()); v->UpdateWorldToEye(f); // Build the solar system //fgSolarSystemInit(*t); FG_LOG(FG_GENERAL, FG_INFO, "Building SolarSystem"); SolarSystem::theSolarSystem = new SolarSystem(t); // Initialize the Stars subsystem if( fgStarsInit() ) { // Stars initialized ok. } else { FG_LOG( FG_GENERAL, FG_ALERT, "Error in Stars initialization!" ); exit(-1); } // Initialize the planetary subsystem // global_events.Register( "fgPlanetsInit()", fgPlanetsInit, // fgEVENT::FG_EVENT_READY, 600000); // Initialize the sun's position // global_events.Register( "fgSunInit()", fgSunInit, // fgEVENT::FG_EVENT_READY, 30000 ); // Intialize the moon's position // global_events.Register( "fgMoonInit()", fgMoonInit, // fgEVENT::FG_EVENT_READY, 600000 ); // register the periodic update of Sun, moon, and planets global_events.Register( "ssolsysUpdate", solarSystemRebuild, fgEVENT::FG_EVENT_READY, 600000); // fgUpdateSunPos() needs a few position and view parameters set // so it can calculate local relative sun angle and a few other // things for correctly orienting the sky. fgUpdateSunPos(); fgUpdateMoonPos(); global_events.Register( "fgUpdateSunPos()", fgUpdateSunPos, fgEVENT::FG_EVENT_READY, 60000); global_events.Register( "fgUpdateMoonPos()", fgUpdateMoonPos, fgEVENT::FG_EVENT_READY, 60000); // Initialize Lighting interpolation tables l->Init(); // update the lighting parameters (based on sun angle) global_events.Register( "fgLight::Update()", fgMethodCallback<fgLIGHT>( &cur_light_params, &fgLIGHT::Update), fgEVENT::FG_EVENT_READY, 30000 ); // Initialize the weather modeling subsystem current_weather.Init(); // Initialize the Cockpit subsystem if( fgCockpitInit( ¤t_aircraft )) { // Cockpit initialized ok. } else { FG_LOG( FG_GENERAL, FG_ALERT, "Error in Cockpit initialization!" ); exit(-1); } // Initialize the "sky" fgSkyInit(); // Initialize the flight model subsystem data structures base on // above values fgFDMInit( current_options.get_flight_model(), cur_fdm_state, 1.0 / DEFAULT_MODEL_HZ ); // I'm just sticking this here for now, it should probably move // eventually scenery.cur_elev = f->get_Runway_altitude() * FEET_TO_METER; if ( f->get_Altitude() < f->get_Runway_altitude() + 3.758099) { f->set_Altitude( f->get_Runway_altitude() + 3.758099 ); } FG_LOG( FG_GENERAL, FG_INFO, "Updated position (after elevation adj): (" << (f->get_Latitude() * RAD_TO_DEG) << ", " << (f->get_Longitude() * RAD_TO_DEG) << ", " << (f->get_Altitude() * FEET_TO_METER) << ")" ); // end of thing that I just stuck in that I should probably move // Joystick support if ( fgJoystickInit() ) { // Joystick initialized ok. } else { FG_LOG( FG_GENERAL, FG_ALERT, "Error in Joystick initialization!" ); } // Autopilot init added here, by Jeff Goeke-Smith fgAPInit(¤t_aircraft); // Initialize serial ports #if ! defined( MACOS ) fgSerialInit(); #endif FG_LOG( FG_GENERAL, FG_INFO, endl); return(1); } void fgReInitSubsystems( void ) { FGInterface *f = current_aircraft.fdm_state; FGView *v = ¤t_view; FGTime *t = FGTime::cur_time_params; int toggle_pause = t->getPause(); if( !toggle_pause ) t->togglePauseMode(); fgInitPosition(); if( fgTileMgrInit() ) { // Load the local scenery data fgTileMgrUpdate(); } else { FG_LOG( FG_GENERAL, FG_ALERT, "Error in Tile Manager initialization!" ); exit(-1); } fgFDMSetGroundElevation( current_options.get_flight_model(), scenery.cur_elev ); // Reset our altitude if we are below ground FG_LOG( FG_GENERAL, FG_DEBUG, "Current altitude = " << f->get_Altitude() ); FG_LOG( FG_GENERAL, FG_DEBUG, "Current runway altitude = " << f->get_Runway_altitude() ); if ( f->get_Altitude() < f->get_Runway_altitude() + 3.758099) { f->set_Altitude( f->get_Runway_altitude() + 3.758099 ); } double sea_level_radius_meters; double lat_geoc; // Set the FG variables first fgGeodToGeoc( f->get_Latitude(), f->get_Altitude(), &sea_level_radius_meters, &lat_geoc); f->set_Geocentric_Position( lat_geoc, f->get_Longitude(), f->get_Altitude() + (sea_level_radius_meters * METER_TO_FEET) ); f->set_Sea_level_radius( sea_level_radius_meters * METER_TO_FEET ); f->set_sin_cos_longitude(f->get_Longitude()); f->set_sin_cos_latitude(f->get_Latitude()); f->set_sin_lat_geocentric(sin(lat_geoc)); f->set_cos_lat_geocentric(cos(lat_geoc)); // The following section sets up the flight model EOM parameters // and should really be read in from one or more files. // Initial Velocity f->set_Velocities_Local( 0.0, 0.0, 0.0 ); // Initial Orientation f->set_Euler_Angles( current_options.get_roll() * DEG_TO_RAD, current_options.get_pitch() * DEG_TO_RAD, current_options.get_heading() * DEG_TO_RAD ); // Initial Angular Body rates f->set_Omega_Body( 7.206685E-05, 0.0, 9.492658E-05 ); f->set_Earth_position_angle( 0.0 ); // Mass properties and geometry values f->set_Inertias( 8.547270E+01, 1.048000E+03, 3.000000E+03, 3.530000E+03, 0.000000E+00 ); // CG position w.r.t. ref. point f->set_CG_Position( 0.0, 0.0, 0.0 ); // Initialize view parameters FG_LOG( FG_GENERAL, FG_DEBUG, "Before v->init()"); v->Init(); FG_LOG( FG_GENERAL, FG_DEBUG, "After v->init()"); v->UpdateViewMath(f); FG_LOG( FG_GENERAL, FG_DEBUG, " abs_view_pos = " << v->get_abs_view_pos()); v->UpdateWorldToEye(f); fgFDMInit( current_options.get_flight_model(), cur_fdm_state, 1.0 / DEFAULT_MODEL_HZ ); scenery.cur_elev = f->get_Runway_altitude() * FEET_TO_METER; if ( f->get_Altitude() < f->get_Runway_altitude() + 3.758099) { f->set_Altitude( f->get_Runway_altitude() + 3.758099 ); } controls.reset_all(); fgAPReset(); if( !toggle_pause ) t->togglePauseMode(); }