]> git.mxchange.org Git - flightgear.git/blobdiff - src/Main/main.cxx
Merge branch 'tat/configure' into next
[flightgear.git] / src / Main / main.cxx
index 14debbd829ffdc7fd70859516b7c43fb683d7764..a982888c003feadb9b37f0ea058620528aeeecd7 100644 (file)
@@ -67,7 +67,6 @@
 #include <ATCDCL/ATCmgr.hxx>
 #include <ATCDCL/AIMgr.hxx>
 #include <Time/tmp.hxx>
-#include <Time/fg_timer.hxx>
 #include <Environment/environment_mgr.hxx>
 #include <GUI/new_gui.hxx>
 #include <MultiPlayer/multiplaymgr.hxx>
@@ -80,6 +79,7 @@
 #include "main.hxx"
 #include "util.hxx"
 #include "fg_init.hxx"
+#include "fg_os.hxx"
 #include "WindowSystemAdapter.hxx"
 
 
@@ -137,7 +137,8 @@ void fgUpdateTimeDepCalcs() {
         // We require just to have 50 meter scenery availabe around
         // the aircraft.
         double range = 1000.0;
-        if (globals->get_scenery()->scenery_available(lat, lon, range)) {
+        SGGeod geod = SGGeod::fromDeg(lon, lat);
+        if (globals->get_scenery()->scenery_available(geod, range)) {
             //SG_LOG(SG_FLIGHT, SG_INFO, "Finally initializing fdm");
             cur_fdm_state->init();
             if ( cur_fdm_state->get_bound() ) {
@@ -177,7 +178,6 @@ void fgUpdateTimeDepCalcs() {
         // do nothing, fdm isn't inited yet
     }
 
-    globals->get_model_mgr()->update(delta_time_sec);
     globals->get_aircraft_model()->update(delta_time_sec);
 
     // Update solar system
@@ -188,15 +188,6 @@ void fgUpdateTimeDepCalcs() {
 }
 
 
-void fgInitTimeDepCalcs( void ) {
-    // noop for now
-}
-
-
-static const double alt_adjust_ft = 3.758099;
-static const double alt_adjust_m = alt_adjust_ft * SG_FEET_TO_METER;
-
-
 // What should we do when we have nothing else to do?  Let's get ready
 // for the next move and update the display?
 static void fgMainLoop( void ) {
@@ -208,6 +199,12 @@ static void fgMainLoop( void ) {
         = fgGetNode("/position/latitude-deg");
     static SGConstPropertyNode_ptr altitude
         = fgGetNode("/position/altitude-ft");
+    static SGConstPropertyNode_ptr vn_fps
+        = fgGetNode("/velocities/speed-north-fps");
+    static SGConstPropertyNode_ptr ve_fps
+        = fgGetNode("/velocities/speed-east-fps");
+    static SGConstPropertyNode_ptr vd_fps
+        = fgGetNode("/velocities/speed-down-fps");
     static SGConstPropertyNode_ptr clock_freeze
         = fgGetNode("/sim/freeze/clock", true);
     static SGConstPropertyNode_ptr cur_time_override
@@ -267,7 +264,7 @@ static void fgMainLoop( void ) {
         }
         current_time_stamp.stamp();
         /* Convert to ms */
-        double elapsed_us = current_time_stamp - last_time_stamp;
+        double elapsed_us = (current_time_stamp - last_time_stamp).toUSecs();
         if ( elapsed_us < frame_us ) {
             double requested_us = frame_us - elapsed_us;
             ulMilliSecondSleep ( (int)(requested_us / 1000.0) ) ;
@@ -280,7 +277,9 @@ static void fgMainLoop( void ) {
         // ulMilliSecondSleep() call is omitted this will peg the cpu
         // (which is just fine if FG is the only app you care about.)
         current_time_stamp.stamp();
-        while ( current_time_stamp - last_time_stamp < frame_us ) {
+        SGTimeStamp next_time_stamp = last_time_stamp;
+        next_time_stamp += SGTimeStamp::fromSec(1e-6*frame_us);
+        while ( current_time_stamp < next_time_stamp ) {
             current_time_stamp.stamp();
         }
     } else {
@@ -288,8 +287,7 @@ static void fgMainLoop( void ) {
         current_time_stamp.stamp();
     }
 
-    real_delta_time_sec
-        = double(current_time_stamp - last_time_stamp) / 1000000.0;
+    real_delta_time_sec = (current_time_stamp - last_time_stamp).toSecs();
 
     // Limit the time we need to spend in simulation loops
     // That means, if the /sim/max-simtime-per-frame value is strictly positive
@@ -306,15 +304,12 @@ static void fgMainLoop( void ) {
 
     // round the real time down to a multiple of 1/model-hz.
     // this way all systems are updated the _same_ amount of dt.
-    {
-        static double rem = 0.0;
-        real_delta_time_sec += rem;
-        double hz = model_hz;
-        double nit = floor(real_delta_time_sec*hz);
-        rem = real_delta_time_sec - nit/hz;
-        real_delta_time_sec = nit/hz;
-    }
-
+    static double reminder = 0.0;
+    real_delta_time_sec += reminder;
+    global_multi_loop = long(floor(real_delta_time_sec*model_hz));
+    global_multi_loop = SGMisc<long>::max(0, global_multi_loop);
+    reminder = real_delta_time_sec - double(global_multi_loop)/double(model_hz);
+    real_delta_time_sec = double(global_multi_loop)/double(model_hz);
 
     if (clock_freeze->getBoolValue() || wait_for_scenery) {
         delta_time_sec = 0;
@@ -328,8 +323,6 @@ static void fgMainLoop( void ) {
     fgSetDouble("/sim/time/delta-realtime-sec", real_delta_time_sec);
     fgSetDouble("/sim/time/delta-sec", delta_time_sec);
 
-    static long remainder = 0;
-    long elapsed;
 #ifdef FANCY_FRAME_COUNTER
     int i;
     double accum;
@@ -402,12 +395,6 @@ static void fgMainLoop( void ) {
                                 altitude->getDoubleValue() * SG_FEET_TO_METER,
                                 globals->get_time_params()->getJD() );
 
-    // Get elapsed time (in usec) for this past frame
-    elapsed = fgGetTimeInterval();
-    SG_LOG( SG_ALL, SG_DEBUG,
-            "Elapsed time interval is = " << elapsed
-            << ", previous remainder is = " << remainder );
-
     // Calculate frame rate average
 #ifdef FANCY_FRAME_COUNTER
     /* old fps calculation */
@@ -454,35 +441,23 @@ static void fgMainLoop( void ) {
         globals->get_AI_mgr()->update(delta_time_sec);
 
     // Run flight model
-
-    // Calculate model iterations needed for next frame
-    elapsed += remainder;
-
-    global_multi_loop = (long)(((double)elapsed * 0.000001) * model_hz );
-    remainder = elapsed - ( (global_multi_loop*1000000) / model_hz );
-    SG_LOG( SG_ALL, SG_DEBUG,
-            "Model iterations needed = " << global_multi_loop
-            << ", new remainder = " << remainder );
-
-    // chop max iterations to something reasonable if the sim was
-    // delayed for an excessive amount of time
-    if ( global_multi_loop > 2.0 * model_hz ) {
-        global_multi_loop = (int)(2.0 * model_hz );
-        remainder = 0;
-    }
-
-    // flight model
-    if ( global_multi_loop > 0) {
+    if (0 < global_multi_loop) {
         // first run the flight model each frame until it is initialized
-        // then continue running each frame only after initial scenery load is complete.
+        // then continue running each frame only after initial scenery
+        // load is complete.
         fgUpdateTimeDepCalcs();
     } else {
         SG_LOG( SG_ALL, SG_DEBUG,
             "Elapsed time is zero ... we're zinging" );
     }
 
-    SGSoundMgr *smgr = globals->get_soundmgr();
-    smgr->update(delta_time_sec);
+    // Run audio scheduler
+#ifdef ENABLE_AUDIO_SUPPORT
+    if ( globals->get_soundmgr()->is_working() ) {
+        globals->get_soundmgr()->update( delta_time_sec );
+    }
+#endif
+
     globals->get_subsystem_mgr()->update(delta_time_sec);
 
     //
@@ -491,46 +466,142 @@ static void fgMainLoop( void ) {
     //   we may want to move this to its own class at some point
     //
     double visibility_meters = fgGetDouble("/environment/visibility-m");
+    FGViewer *current_view = globals->get_current_view();
 
     globals->get_tile_mgr()->prep_ssg_nodes( visibility_meters );
     // update tile manager for view...
-    SGLocation *view_location = globals->get_current_view()->getSGLocation();
-    globals->get_tile_mgr()->update( view_location, visibility_meters );
-    {
-        double lon = view_location->getLongitude_deg();
-        double lat = view_location->getLatitude_deg();
-        double alt = view_location->getAltitudeASL_ft() * SG_FEET_TO_METER;
-
-        // check if we can reuse the groundcache for that purpose.
-        double ref_time, r;
-        SGVec3d pt;
-        bool valid = cur_fdm_state->is_valid_m(&ref_time, pt.sg(), &r);
-        SGVec3d viewpos(globals->get_current_view()->get_view_pos());
-        if (valid && distSqr(viewpos, pt) < r*r) {
-            // Reuse the cache ...
-            double lev
-                = cur_fdm_state->get_groundlevel_m(lat*SGD_DEGREES_TO_RADIANS,
-                                                   lon*SGD_DEGREES_TO_RADIANS,
-                                                   alt + 2.0);
-            view_location->set_cur_elev_m( lev );
-        } else {
-            // Do full intersection test.
-            double lev;
-            if (globals->get_scenery()->get_elevation_m(lat, lon, alt+2, lev, 0))
-                view_location->set_cur_elev_m( lev );
-            else
-                view_location->set_cur_elev_m( -9999.0 );
-        }
-    }
+    SGVec3d viewPos = globals->get_current_view()->get_view_pos();
+    SGGeod geodViewPos = SGGeod::fromCart(viewPos);
+    globals->get_tile_mgr()->update(geodViewPos, visibility_meters);
 
     // run Nasal's settimer() loops right before the view manager
     globals->get_event_mgr()->update(delta_time_sec);
 
+    // pick up model coordidnates that Nasal code may have set relative to the
+    // aircraft's
+    globals->get_model_mgr()->update(delta_time_sec);
+
     // update the view angle as late as possible, but before sound calculations
-    globals->get_viewmgr()->update(delta_time_sec);
+    globals->get_viewmgr()->update(real_delta_time_sec);
 
-    // Do any I/O channel work that might need to be done (must come after viewmgr)
-    globals->get_io()->update(real_delta_time_sec);
+#ifdef ENABLE_AUDIO_SUPPORT
+    if ( globals->get_soundmgr()->is_working() ) {
+        // Right now we make a simplifying assumption that the primary
+        // aircraft is the source of all sounds and that all sounds are
+        // positioned in the aircraft base
+
+        static sgdVec3 last_listener_pos = {0, 0, 0};
+        static sgdVec3 last_model_pos = {0, 0, 0};
+
+        // get the orientation
+        const SGQuatd view_or = current_view->getViewOrientation();
+        SGQuatd surf_or = SGQuatd::fromLonLat(current_view->getPosition());
+        SGQuatd model_or = SGQuatd::fromYawPitchRollDeg(
+            globals->get_aircraft_model()->get3DModel()->getHeadingDeg(),
+            globals->get_aircraft_model()->get3DModel()->getPitchDeg(),
+            globals->get_aircraft_model()->get3DModel()->getRollDeg());
+
+        // get the up and at vector in the aircraft base
+        // (ok, the up vector is a down vector, but the coordinates
+        // are finally calculated in a left hand system and openal
+        // lives in a right hand system. Therefore we need to pass
+        // the down vector to get correct stereo sound.)
+        SGVec3d sgv_up = model_or.rotateBack(
+            surf_or.rotateBack(view_or.rotate(SGVec3d(0, 1, 0))));
+        sgVec3 up;
+        sgSetVec3(up, sgv_up[0], sgv_up[1], sgv_up[2]);
+        SGVec3d sgv_at = model_or.rotateBack(
+        surf_or.rotateBack(view_or.rotate(SGVec3d(0, 0, 1))));
+        sgVec3 at;
+        sgSetVec3(at, sgv_at[0], sgv_at[1], sgv_at[2]);
+
+        // get the location data for the primary FDM (now hardcoded to ac model)...
+        SGGeod geodPos = globals->get_aircraft_model()->get3DModel()->getPosition();
+        SGVec3d model_pos = SGVec3d::fromGeod(geodPos);
+
+        // Calculate speed of listener and model.  This code assumes the
+        // listener is either tracking the model at the same speed or
+        // stationary.
+
+        sgVec3 listener_vel, model_vel;
+        SGVec3d SGV3d_help;
+        sgdVec3 sgdv3_help;
+        sgdVec3 sgdv3_null = {0, 0, 0};
+
+        // the aircraft velocity as reported by the fdm (this will not
+        // vary or be affected by frame rates or timing jitter.)
+        sgVec3 fdm_vel_vec;
+        sgSetVec3( fdm_vel_vec,
+                   vn_fps->getDoubleValue() * SG_FEET_TO_METER,
+                   ve_fps->getDoubleValue() * SG_FEET_TO_METER,
+                   vd_fps->getDoubleValue() * SG_FEET_TO_METER );
+        double fdm_vel = sgLengthVec3(fdm_vel_vec);
+
+        // compute the aircraft velocity vector and scale it to the length
+        // of the fdm velocity vector.  This gives us a vector in the
+        // proper coordinate system, but also with the proper time
+        // invariant magnitude.
+        sgdSubVec3( sgdv3_help,
+                last_model_pos, model_pos.data());
+        sgdAddVec3( last_model_pos, sgdv3_null, model_pos.data());
+        SGV3d_help = model_or.rotateBack(
+        surf_or.rotateBack(SGVec3d(sgdv3_help[0],
+        sgdv3_help[1], sgdv3_help[2])));
+        sgSetVec3( model_vel, SGV3d_help[0], SGV3d_help[1], SGV3d_help[2]);
+
+        float vel = sgLengthVec3(model_vel);
+        if ( fabs(vel) > 0.0001 ) {
+            if ( fabs(fdm_vel / vel) > 0.0001 ) {
+                sgScaleVec3( model_vel, fdm_vel / vel );
+            }
+        }
+
+        // check for moving or stationary listener (view position)
+        sgdSubVec3( sgdv3_help,
+                    last_listener_pos, current_view->get_view_pos().data());
+        sgdAddVec3( last_listener_pos,
+                    sgdv3_null, current_view->get_view_pos().data());
+
+        if ( sgdLengthVec3(sgdv3_help) > 0.2 ) {
+            sgCopyVec3( listener_vel, model_vel );
+        } else {
+            sgSetVec3( listener_vel, 0.0, 0.0, 0.0 );
+        }
+
+        globals->get_soundmgr()->set_listener_vel( listener_vel );
+
+        // set positional offset for sources
+        sgdVec3 dsource_pos_offset;
+        sgdSubVec3( dsource_pos_offset,
+                    current_view->get_view_pos().data(),
+                    model_pos.data() );
+        SGVec3d sgv_dsource_pos_offset = model_or.rotateBack(
+        surf_or.rotateBack(SGVec3d(dsource_pos_offset[0],
+        dsource_pos_offset[1], dsource_pos_offset[2])));
+
+        sgVec3 source_pos_offset;
+        sgSetVec3(source_pos_offset, sgv_dsource_pos_offset[0],
+        sgv_dsource_pos_offset[1], sgv_dsource_pos_offset[2]);
+
+        globals->get_soundmgr()->set_source_pos_all( source_pos_offset );
+
+        float orient[6];
+        for (int i = 0; i < 3; i++) {
+            orient[i] = sgv_at[i];
+            orient[i + 3] = sgv_up[i];
+        }
+        globals->get_soundmgr()->set_listener_orientation( orient );
+
+        // set the velocity
+        // all sources are defined to be in the model
+        globals->get_soundmgr()->set_source_vel_all( model_vel );
+
+        // The listener is always positioned at the origin.
+        sgVec3 listener_pos;
+        sgSetVec3( listener_pos, 0.0, 0.0, 0.0 );
+        globals->get_soundmgr()->set_listener_pos( listener_pos );
+    }
+#endif
 
     // END Tile Manager udpates
 
@@ -727,10 +798,7 @@ static void fgIdleFunction ( void ) {
         // Sun diameter: 1,390,000 kilometers
         thesky->build( 80000.0, 80000.0,
                        463.3, 361.8,
-                       globals->get_ephem()->getNumPlanets(),
-                       globals->get_ephem()->getPlanets(),
-                       globals->get_ephem()->getNumStars(),
-                       globals->get_ephem()->getStars(),
+                       *globals->get_ephem(),
                        fgGetNode("/environment", true));
 
         // Initialize MagVar model
@@ -826,16 +894,17 @@ static void fgIdleFunction ( void ) {
 
 static void upper_case_property(const char *name)
 {
+    using namespace simgear;
     SGPropertyNode *p = fgGetNode(name, false);
     if (!p) {
         p = fgGetNode(name, true);
         p->setStringValue("");
     } else {
-        SGPropertyNode::Type t = p->getType();
-        if (t == SGPropertyNode::NONE || t == SGPropertyNode::UNSPECIFIED)
+        props::Type t = p->getType();
+        if (t == props::NONE || t == props::UNSPECIFIED)
             p->setStringValue("");
         else
-            assert(t == SGPropertyNode::STRING);
+            assert(t == props::STRING);
     }
     p->addChangeListener(new FGMakeUpperCase);
 }
@@ -882,7 +951,7 @@ bool fgMainInit( int argc, char **argv ) {
     fgInitFGRoot(argc, argv);
 
     // Check for the correct base package version
-    static char required_version[] = "1.0.0";
+    static char required_version[] = "1.9.0";
     string base_version = fgBasePackageVersion();
     if ( !(base_version == required_version) ) {
         // tell the operator how to use this application