]> git.mxchange.org Git - flightgear.git/commitdiff
Create TimeManager subsystem, and collect the time related code out of main.cxx and...
authorJames Turner <zakalawe@mac.com>
Tue, 13 Jul 2010 20:50:44 +0000 (21:50 +0100)
committerJames Turner <zakalawe@mac.com>
Sun, 1 Aug 2010 19:33:11 +0000 (20:33 +0100)
Remove the unfortunately named 'tmp.[cxx|hxx]', pushing the remaining code in FGLight.

17 files changed:
projects/VC90/FlightGear/FlightGear.vcproj
src/Main/fg_commands.cxx
src/Main/fg_init.cxx
src/Main/fg_init.hxx
src/Main/main.cxx
src/Main/main.hxx
src/Main/renderer.cxx
src/Network/native_fdm.cxx
src/Network/native_gui.cxx
src/Time/Makefile.am
src/Time/TimeManager.cxx [new file with mode: 0644]
src/Time/TimeManager.hxx [new file with mode: 0644]
src/Time/light.cxx
src/Time/light.hxx
src/Time/sunsolver.cxx
src/Time/tmp.cxx [deleted file]
src/Time/tmp.hxx [deleted file]

index 9bf22509d9d275ba17b96e1d4cfbaea5275fb4c4..eacb7a081dc0317f94ed2c0f929dedec049cf964 100644 (file)
                                >
                        </File>
                        <File
-                               RelativePath="..\..\..\src\Time\tmp.cxx"
+                               RelativePath="..\..\..\src\Time\TimeManager.cxx"
                                >
                        </File>
                        <File
-                               RelativePath="..\..\..\src\Time\tmp.hxx"
+                               RelativePath="..\..\..\src\Time\TimeManager.hxx"
                                >
                        </File>
                </Filter>
index 1dd37d387e8912f2e11cc24a4f6643994c1c74e3..c277b6b73a4bd259636b8b81bf033768a4ee1cc1 100644 (file)
@@ -37,7 +37,6 @@
 #include <Scripting/NasalSys.hxx>
 #include <Sound/sample_queue.hxx>
 #include <Time/sunsolver.hxx>
-#include <Time/tmp.hxx>
 
 #include "fg_init.hxx"
 #include "fg_io.hxx"
index 7805ac413c6950c8e111a63824a818080825a37f..36c5a17ffa23ef425c4769b3909a0e2d6a6b84b7 100644 (file)
@@ -62,8 +62,6 @@
 #include <simgear/scene/material/matlib.hxx>
 #include <simgear/scene/model/particles.hxx>
 #include <simgear/sound/soundmgr_openal.hxx>
-#include <simgear/timing/sg_time.hxx>
-#include <simgear/timing/lowleveltime.h>
 
 #include <Aircraft/controls.hxx>
 #include <Aircraft/replay.hxx>
 #include <Sound/voice.hxx>
 #include <Systems/system_mgr.hxx>
 #include <Time/light.hxx>
-#include <Time/sunsolver.hxx>
-#include <Time/tmp.hxx>
 #include <Traffic/TrafficMgr.hxx>
 #include <MultiPlayer/multiplaymgr.hxx>
 #include <FDM/fdm_shell.hxx>
@@ -1272,140 +1268,6 @@ void fgInitView() {
   globals->get_viewmgr()->update(0);
 }
 
-
-SGTime *fgInitTime() {
-    // Initialize time
-    static const SGPropertyNode *longitude
-        = fgGetNode("/position/longitude-deg");
-    static const SGPropertyNode *latitude
-        = fgGetNode("/position/latitude-deg");
-    static const SGPropertyNode *cur_time_override
-        = fgGetNode("/sim/time/cur-time-override", true);
-
-    SGPath zone( globals->get_fg_root() );
-    zone.append( "Timezone" );
-    SGTime *t = new SGTime( longitude->getDoubleValue()
-                              * SGD_DEGREES_TO_RADIANS,
-                            latitude->getDoubleValue()
-                              * SGD_DEGREES_TO_RADIANS,
-                            zone.str(),
-                            cur_time_override->getLongValue() );
-
-    globals->set_warp_delta( 0 );
-
-    t->update( 0.0, 0.0,
-               cur_time_override->getLongValue(),
-               globals->get_warp() );
-
-    return t;
-}
-
-
-// set up a time offset (aka warp) if one is specified
-void fgInitTimeOffset() {
-    static const SGPropertyNode *longitude
-        = fgGetNode("/position/longitude-deg");
-    static const SGPropertyNode *latitude
-        = fgGetNode("/position/latitude-deg");
-    static const SGPropertyNode *cur_time_override
-        = fgGetNode("/sim/time/cur-time-override", true);
-
-    // Handle potential user specified time offsets
-    int orig_warp = globals->get_warp();
-    SGTime *t = globals->get_time_params();
-    time_t cur_time = t->get_cur_time();
-    time_t currGMT = sgTimeGetGMT( gmtime(&cur_time) );
-    time_t systemLocalTime = sgTimeGetGMT( localtime(&cur_time) );
-    time_t aircraftLocalTime = 
-        sgTimeGetGMT( fgLocaltime(&cur_time, t->get_zonename() ) );
-    
-    // Okay, we now have several possible scenarios
-    int offset = fgGetInt("/sim/startup/time-offset");
-    string offset_type = fgGetString("/sim/startup/time-offset-type");
-
-    int warp = 0;
-    if ( offset_type == "real" ) {
-        warp = 0;
-    } else if ( offset_type == "dawn" ) {
-        warp = fgTimeSecondsUntilSunAngle( cur_time,
-                                           longitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           latitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           90.0, true ); 
-    } else if ( offset_type == "morning" ) {
-        warp = fgTimeSecondsUntilSunAngle( cur_time,
-                                           longitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           latitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           75.0, true ); 
-    } else if ( offset_type == "noon" ) {
-        warp = fgTimeSecondsUntilSunAngle( cur_time,
-                                           longitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           latitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           0.0, true ); 
-    } else if ( offset_type == "afternoon" ) {
-        warp = fgTimeSecondsUntilSunAngle( cur_time,
-                                           longitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           latitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           60.0, false ); 
-     } else if ( offset_type == "dusk" ) {
-        warp = fgTimeSecondsUntilSunAngle( cur_time,
-                                           longitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           latitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           90.0, false ); 
-     } else if ( offset_type == "evening" ) {
-        warp = fgTimeSecondsUntilSunAngle( cur_time,
-                                           longitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           latitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           100.0, false ); 
-    } else if ( offset_type == "midnight" ) {
-        warp = fgTimeSecondsUntilSunAngle( cur_time,
-                                           longitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           latitude->getDoubleValue()
-                                             * SGD_DEGREES_TO_RADIANS,
-                                           180.0, false ); 
-    } else if ( offset_type == "system-offset" ) {
-        warp = offset;
-       orig_warp = 0;
-    } else if ( offset_type == "gmt-offset" ) {
-        warp = offset - (currGMT - systemLocalTime);
-       orig_warp = 0;
-    } else if ( offset_type == "latitude-offset" ) {
-        warp = offset - (aircraftLocalTime - systemLocalTime);
-       orig_warp = 0;
-    } else if ( offset_type == "system" ) {
-      warp = offset - (systemLocalTime - currGMT) - cur_time;
-    } else if ( offset_type == "gmt" ) {
-        warp = offset - cur_time;
-    } else if ( offset_type == "latitude" ) {
-        warp = offset - (aircraftLocalTime - currGMT)- cur_time; 
-    } else {
-        SG_LOG( SG_GENERAL, SG_ALERT,
-                "FG_TIME::Unsupported offset type " << offset_type );
-        exit( -1 );
-    }
-    globals->set_warp( orig_warp + warp );
-    t->update( longitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS,
-               latitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS,
-               cur_time_override->getLongValue(),
-               globals->get_warp() );
-
-    SG_LOG( SG_GENERAL, SG_INFO, "After fgInitTimeOffset(): warp = " 
-            << globals->get_warp() );
-}
-
-
 // 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.
@@ -1528,17 +1390,6 @@ bool fgInitSubsystems() {
 
     globals->add_subsystem("gui", new NewGUI, SGSubsystemMgr::INIT);
 
-
-    ////////////////////////////////////////////////////////////////////
-    // Initialize the local time subsystem.
-    ////////////////////////////////////////////////////////////////////
-
-    // update the current timezone each 30 minutes
-    globals->get_event_mgr()->addTask( "fgUpdateLocalTime()",
-                                       &fgUpdateLocalTime, 30*60 );
-    fgInitTimeOffset();                // the environment subsystem needs this
-
-
     ////////////////////////////////////////////////////////////////////
     // Initialize the lighting subsystem.
     ////////////////////////////////////////////////////////////////////
@@ -1714,10 +1565,7 @@ void fgReInitSubsystems()
 
     globals->get_controls()->reset_all();
 
-    fgUpdateLocalTime();
-
-    // re-init to proper time of day setting
-    fgInitTimeOffset();
+    globals->get_subsystem("time")->reinit();
 
     if ( !freeze ) {
         fgSetBool("/sim/freeze/master", false);
@@ -1743,11 +1591,6 @@ void doSimulatorReset(void)  // from gui_local.cxx -- TODO merge with fgReInitSu
     // update our position based on current presets
     fgInitPosition();
 
-    SGTime *t = globals->get_time_params();
-    delete t;
-    t = fgInitTime();
-    globals->set_time_params(t);
-
     fgReInitSubsystems();
 
     globals->get_tile_mgr()->update(fgGetDouble("/environment/visibility-m"));
index da68ab2e22fabb52546007897d5ddcceca4817ab..256716a8800eda171de5f0c636eb9647d45cbfb3 100644 (file)
@@ -79,14 +79,6 @@ bool fgInitPosition();
 // Listen to /sim/tower/airport-id and set tower view position accordingly
 void fgInitTowerLocationListener();
 
-
-// Initialize various time dependent systems (lighting, sun position, etc.)
-// returns a new instance of the SGTime class
-SGTime *fgInitTime();
-
-// set up a time offset (aka warp) if one is specified
-void fgInitTimeOffset();
-
 /*
  * Search in the current directory, and in on directory deeper
  * for <aircraft>-set.xml configuration files and show the aircaft name
index 789d80ce885eaa6ce54a3dde72d6920b6e6d1663..935bdd9cd0ab08c3f619292cca519591e506230a 100644 (file)
@@ -34,8 +34,6 @@
 
 #include <iostream>
 
-#include <plib/netSocket.h>
-
 #include <osg/Camera>
 #include <osg/GraphicsContext>
 #include <osgDB/Registry>
@@ -67,7 +65,7 @@
 #include <Sound/fg_fx.hxx>
 #include <ATCDCL/ATCmgr.hxx>
 #include <ATCDCL/AIMgr.hxx>
-#include <Time/tmp.hxx>
+#include <Time/TimeManager.hxx>
 #include <Environment/environment_mgr.hxx>
 #include <Environment/ephemeris.hxx>
 #include <GUI/new_gui.hxx>
@@ -85,8 +83,6 @@
 #include "WindowSystemAdapter.hxx"
 #include <Main/viewer.hxx>
 
-static double real_delta_time_sec = 0.0;
-double delta_time_sec = 0.0;
 
 using namespace flightgear;
 
@@ -99,10 +95,7 @@ FGGeneral general;
 // our initializations out of the idle callback so that we can get a
 // splash screen up and running right away.
 int idle_state = 0;
-long global_multi_loop;
 
-SGTimeStamp last_time_stamp;
-SGTimeStamp current_time_stamp;
 
 void fgInitSoundManager();
 void fgSetNewSoundDevice(const char *);
@@ -114,8 +107,7 @@ extern int _bootstrap_OSInit;
 // 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 ) {
-    int model_hz = fgGetInt("/sim/model-hz");
-
+    
     static SGConstPropertyNode_ptr longitude
         = fgGetNode("/position/longitude-deg");
     static SGConstPropertyNode_ptr latitude
@@ -128,172 +120,24 @@ static void fgMainLoop( void ) {
         = 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
-        = fgGetNode("/sim/time/cur-time-override", true);
-    static SGConstPropertyNode_ptr max_simtime_per_frame
-        = fgGetNode("/sim/max-simtime-per-frame", true);
+      
     static SGPropertyNode_ptr frame_signal
         = fgGetNode("/sim/signals/frame", true);
 
     frame_signal->fireValueChanged();
     SGCloudLayer::enable_bump_mapping = fgGetBool("/sim/rendering/bump-mapping");
-
-    bool scenery_loaded = fgGetBool("sim/sceneryloaded");
-    bool wait_for_scenery = !(scenery_loaded || fgGetBool("sim/sceneryloaded-override"));
-
-    // Update the elapsed time.
-    static bool first_time = true;
-    if ( first_time ) {
-        last_time_stamp.stamp();
-        first_time = false;
-    }
-
-    double throttle_hz = fgGetDouble("/sim/frame-rate-throttle-hz", 0.0);
-    if ( throttle_hz > 0.0 && !wait_for_scenery ) {
-        // optionally throttle the frame rate (to get consistent frame
-        // rates or reduce cpu usage.
-
-        double frame_us = 1000000.0 / throttle_hz;
-
-#define FG_SLEEP_BASED_TIMING 1
-#if defined(FG_SLEEP_BASED_TIMING)
-        // sleep based timing loop.
-        //
-        // Calling sleep, even usleep() on linux is less accurate than
-        // we like, but it does free up the cpu for other tasks during
-        // the sleep so it is desirable.  Because of the way sleep()
-        // is implemented in consumer operating systems like windows
-        // and linux, you almost always sleep a little longer than the
-        // requested amount.
-        //
-        // To combat the problem of sleeping too long, we calculate the
-        // desired wait time and shorten it by 2000us (2ms) to avoid
-        // [hopefully] over-sleep'ing.  The 2ms value was arrived at
-        // via experimentation.  We follow this up at the end with a
-        // simple busy-wait loop to get the final pause timing exactly
-        // right.
-        //
-        // Assuming we don't oversleep by more than 2000us, this
-        // should be a reasonable compromise between sleep based
-        // waiting, and busy waiting.
-
-        // sleep() will always overshoot by a bit so undersleep by
-        // 2000us in the hopes of never oversleeping.
-        frame_us -= 2000.0;
-        if ( frame_us < 0.0 ) {
-            frame_us = 0.0;
-        }
-        current_time_stamp.stamp();
-        /* Convert to ms */
-        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) ) ;
-        }
-#endif
-
-        // busy wait timing loop.
-        //
-        // This yields the most accurate timing.  If the previous
-        // 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();
-        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 {
-        // run as fast as the app will go
-        current_time_stamp.stamp();
-    }
-
-    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
-    // you can limit the maximum amount of time you will do simulations for
-    // one frame to display. The cpu time spent in simulations code is roughly
-    // at least O(real_delta_time_sec). If this is (due to running debug
-    // builds or valgrind or something different blowing up execution times)
-    // larger than the real time you will no longer get any response
-    // from flightgear. This limits that effect. Just set to property from
-    // your .fgfsrc or commandline ...
-    double dtMax = max_simtime_per_frame->getDoubleValue();
-    if (0 < dtMax && dtMax < real_delta_time_sec)
-        real_delta_time_sec = dtMax;
-
-    SGSubsystemGroup* fdmGroup = 
-      globals->get_subsystem_mgr()->get_group(SGSubsystemMgr::FDM);
-    fdmGroup->set_fixed_update_time(1.0 / model_hz);
-
-    // 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 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;
-    } else {
-        delta_time_sec = real_delta_time_sec;
-    }
-    last_time_stamp = current_time_stamp;
-    globals->inc_sim_time_sec( delta_time_sec );
-
-    // These are useful, especially for Nasal scripts.
-    fgSetDouble("/sim/time/delta-realtime-sec", real_delta_time_sec);
-    fgSetDouble("/sim/time/delta-sec", delta_time_sec);
-
-#ifdef FANCY_FRAME_COUNTER
-    int i;
-    double accum;
-#else
-    static time_t last_time = 0;
-    static int frames = 0;
-#endif // FANCY_FRAME_COUNTER
-
-    SGTime *t = globals->get_time_params();
-
+    
     SG_LOG( SG_ALL, SG_DEBUG, "Running Main Loop");
     SG_LOG( SG_ALL, SG_DEBUG, "======= ==== ====");
-
-    // update "time"
-    static bool last_clock_freeze = false;
-
-    if ( clock_freeze->getBoolValue() ) {
-        // clock freeze requested
-        if ( cur_time_override->getLongValue() == 0 ) {
-            fgSetLong( "/sim/time/cur-time-override", t->get_cur_time() );
-            globals->set_warp( 0 );
-        }
-    } else {
-        // no clock freeze requested
-        if ( last_clock_freeze == true ) {
-            // clock just unfroze, let's set warp as the difference
-            // between frozen time and current time so we don't get a
-            // time jump (and corresponding sky object and lighting
-            // jump.)
-            globals->set_warp( cur_time_override->getLongValue() - time(NULL) );
-            fgSetLong( "/sim/time/cur-time-override", 0 );
-        }
-        if ( globals->get_warp_delta() != 0 ) {
-            globals->inc_warp( globals->get_warp_delta() );
-        }
-    }
-
-    last_clock_freeze = clock_freeze->getBoolValue();
-
-    t->update( longitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS,
-               latitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS,
-               cur_time_override->getLongValue(),
-               globals->get_warp() );
-
+    
+    
+  // 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);
+    
     if (globals->get_warp_delta() != 0) {
         FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
         l->update( 0.5 );
@@ -307,36 +151,6 @@ static void fgMainLoop( void ) {
                                 altitude->getDoubleValue() * SG_FEET_TO_METER,
                                 globals->get_time_params()->getJD() );
 
-    // Calculate frame rate average
-#ifdef FANCY_FRAME_COUNTER
-    /* old fps calculation */
-    if ( elapsed > 0 ) {
-        double tmp;
-        accum = 0.0;
-        for ( i = FG_FRAME_RATE_HISTORY - 2; i >= 0; i-- ) {
-            tmp = general.get_frame(i);
-            accum += tmp;
-            // printf("frame[%d] = %.2f\n", i, g->frames[i]);
-            general.set_frame(i+1,tmp);
-        }
-        tmp = 1000000.0 / (float)elapsed;
-        general.set_frame(0,tmp);
-        // printf("frame[0] = %.2f\n", general.frames[0]);
-        accum += tmp;
-        general.set_frame_rate(accum / (float)FG_FRAME_RATE_HISTORY);
-        // printf("ave = %.2f\n", general.frame_rate);
-    }
-#else
-    if ( (t->get_cur_time() != last_time) && (last_time > 0) ) {
-        general.set_frame_rate( frames );
-        fgSetInt("/sim/frame-rate", frames);
-        SG_LOG( SG_ALL, SG_DEBUG,
-                "--> Frame rate is = " << general.get_frame_rate() );
-        frames = 0;
-    }
-    last_time = t->get_cur_time();
-    ++frames;
-#endif
 
     // Update any multiplayer's network queues, the AIMultiplayer
     // implementation is an AI model and depends on that
@@ -345,7 +159,7 @@ static void fgMainLoop( void ) {
 #if ENABLE_ATCDCL  
     // Run ATC subsystem
     if (fgGetBool("/sim/atc/enabled"))
-        globals->get_ATC_mgr()->update(delta_time_sec);
+        globals->get_ATC_mgr()->update(sim_dt);
 
 
     // Run the AI subsystem
@@ -356,11 +170,11 @@ static void fgMainLoop( void ) {
     // depricated AI_mgr system. So, we can safely skip the following
     // two lines at compile time when compiling with --disable-atcdcl
     if (fgGetBool("/sim/ai-traffic/enabled"))
-        globals->get_AI_mgr()->update(delta_time_sec);
+        globals->get_AI_mgr()->update(sim_dt);
 #endif  
     
-    globals->get_subsystem_mgr()->update(delta_time_sec);
-    globals->get_aircraft_model()->update(delta_time_sec);
+    globals->get_subsystem_mgr()->update(sim_dt);
+    globals->get_aircraft_model()->update(sim_dt);
     
     //
     // Tile Manager updates - see if we need to load any new scenery tiles.
@@ -376,14 +190,14 @@ static void fgMainLoop( void ) {
     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);
+    globals->get_event_mgr()->update(sim_dt);
 
     // pick up model coordidnates that Nasal code may have set relative to the
     // aircraft's
-    globals->get_model_mgr()->update(delta_time_sec);
+    globals->get_model_mgr()->update(sim_dt);
 
     // update the view angle as late as possible, but before sound calculations
-    globals->get_viewmgr()->update(real_delta_time_sec);
+    globals->get_viewmgr()->update(real_dt);
 
     // 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-
@@ -419,13 +233,13 @@ static void fgMainLoop( void ) {
         if (smgr_enabled == true) {
             static SGPropertyNode *volume = fgGetNode("/sim/sound/volume");
             smgr->set_volume(volume->getFloatValue());
-            smgr->update(delta_time_sec);
+            smgr->update(sim_dt);
         }
     }
 #endif
 
     // END Tile Manager udpates
-
+    bool scenery_loaded = fgGetBool("sim/sceneryloaded");
     if (!scenery_loaded && globals->get_tile_mgr()->isSceneryLoaded()
         && fgGetBool("sim/fdm-initialized")) {
         fgSetBool("sim/sceneryloaded",true);
@@ -566,9 +380,10 @@ static void fgIdleFunction ( void ) {
         fgInitPosition();
         fgInitTowerLocationListener();
 
-        SGTime *t = fgInitTime();
-        globals->set_time_params( t );
-
+        TimeManager* t = new TimeManager;
+        globals->add_subsystem("time", t, SGSubsystemMgr::INIT);
+        t->init(); // need to init now, not during initSubsystems
+        
         // Do some quick general initializations
         if( !fgInitGeneral()) {
             SG_LOG( SG_GENERAL, SG_ALERT,
@@ -733,10 +548,7 @@ static void fgIdleFunction ( void ) {
 
     } else if ( idle_state == 8 ) {
         idle_state = 1000;
-        // Initialize the time offset (warp) after fgInitSubsystem
-        // (which initializes the lighting interpolation tables.)
-        fgInitTimeOffset();
-
+        
         // setup OpenGL view parameters
         globals->get_renderer()->init();
 
index b15846b5a9a15ec3f5234d02c294c09bf8f34d3e..2117f605b9cd2f6f7291a413f9e2457bbca3ee3a 100644 (file)
@@ -8,8 +8,6 @@ bool fgMainInit( int argc, char **argv );
 
 
 extern int idle_state;
-extern long global_multi_loop;
-extern double delta_time_sec;
 
 extern char *homedir;
 extern char *hostname;
index 3cd5a76186aee751a143066c2c5b5d4047099f42..a3d6d988651ccae043f96a605bba6274b1350cc4 100644 (file)
@@ -563,16 +563,12 @@ FGRenderer::init( void )
 // Update all Visuals (redraws anything graphics related)
 void
 FGRenderer::update( bool refresh_camera_settings ) {
-    bool scenery_loaded = fgGetBool("sim/sceneryloaded")
+    bool scenery_loaded = fgGetBool("sim/sceneryloaded", false)
                           || fgGetBool("sim/sceneryloaded-override");
     osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
-    if ( idle_state < 1000 || !scenery_loaded ) {
-        fgSetDouble("/sim/startup/splash-alpha", 1.0);
-
-        // Keep resetting sim time while the sim is initializing
-        // the splash screen is now in the scenegraph
-        globals->set_sim_time_sec( 0.0 );
-        return;
+    if (!scenery_loaded) {
+      fgSetDouble("/sim/startup/splash-alpha", 1.0);
+      return;
     }
 
     // Fade out the splash screen over the first three seconds.
@@ -629,9 +625,7 @@ FGRenderer::update( bool refresh_camera_settings ) {
     thesky->set_visibility(visibility_meters);
 
     double altitude_m = fgGetDouble("/position/altitude-ft") * SG_FEET_TO_METER;
-    thesky->modify_vis( altitude_m,
-                        ( global_multi_loop * fgGetInt("/sim/speed-up") )
-                        / (double)fgGetInt("/sim/model-hz") );
+    thesky->modify_vis( altitude_m, 0.0 /* time factor, now unused */);
 
     // update the sky dome
     if ( skyblend ) {
@@ -673,7 +667,8 @@ FGRenderer::update( bool refresh_camera_settings ) {
         scolor.cloud_color = SGVec3f(l->cloud_color().data());
         scolor.sun_angle   = l->get_sun_angle();
         scolor.moon_angle  = l->get_moon_angle();
-
+  
+        double delta_time_sec = fgGetDouble("/sim/time/delta-sec");
         thesky->reposition( sstate, *globals->get_ephem(), delta_time_sec );
         thesky->repaint( scolor, *globals->get_ephem() );
 
index bc28f928a6219cc7317449c00f8abb66896947fd..46fb62d1ab857710b8a594d7af24cd1ec0f29918 100644 (file)
@@ -31,7 +31,6 @@
 #include <simgear/timing/sg_time.hxx>
 
 #include <FDM/flightProperties.hxx>
-#include <Time/tmp.hxx>
 #include <Main/fg_props.hxx>
 #include <Main/globals.hxx>
 #include <Scenery/scenery.hxx>
index 6ddb8349612fbd0d6929a2fa5cd85bbc05781e73..eaae3c32a0adbabb07b8242d5621b88d46f7616a 100644 (file)
@@ -30,7 +30,6 @@
 #include <simgear/io/iochannel.hxx>
 #include <simgear/timing/sg_time.hxx>
 
-#include <Time/tmp.hxx>
 #include <Main/fg_props.hxx>
 #include <Main/globals.hxx>
 #include <Scenery/scenery.hxx>
index 7c824d8d0cc85de7a4a0331986c6898f74e7b921..5db2d7b26c68429e7e8d1c42657fc39e21994934 100644 (file)
@@ -3,6 +3,6 @@ noinst_LIBRARIES = libTime.a
 libTime_a_SOURCES = \
        light.cxx light.hxx \
        sunsolver.cxx sunsolver.hxx \
-       tmp.cxx tmp.hxx
+       TimeManager.cxx TimeManager.hxx
 
 INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
diff --git a/src/Time/TimeManager.cxx b/src/Time/TimeManager.cxx
new file mode 100644 (file)
index 0000000..1adfbbf
--- /dev/null
@@ -0,0 +1,359 @@
+// TimeManager.cxx -- simulation-wide time management
+//
+// Written by James Turner, started July 2010.
+//
+// Copyright (C) 2010  Curtis L. Olson  - http://www.flightgear.org/~curt
+//
+// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "TimeManager.hxx"
+
+#ifdef _WIN32
+#  define WIN32_LEAN_AND_MEAN
+#  include <windows.h> // for Sleep()
+#else
+#  include <unistd.h> // for usleep()
+#endif
+
+#include <simgear/timing/sg_time.hxx>
+#include <simgear/structure/event_mgr.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/timing/lowleveltime.h>
+
+#include <Main/fg_props.hxx>
+#include <Main/globals.hxx>
+#include <Time/sunsolver.hxx>
+
+TimeManager::TimeManager() :
+  _inited(false),
+  _impl(NULL)
+{
+  
+}
+
+void TimeManager::init()
+{
+  if (_inited) {
+    // time manager has to be initialised early, so needs to be defensive
+    // about multiple initialisation 
+    return; 
+  }
+  
+  _firstUpdate = true;
+  _inited = true;
+  _dtRemainder = 0.0;
+  
+  _maxDtPerFrame = fgGetNode("/sim/max-simtime-per-frame", true);
+  _clockFreeze = fgGetNode("/sim/freeze/clock", true);
+  _timeOverride = fgGetNode("/sim/time/cur-time-override", true);
+  
+  _longitudeDeg = fgGetNode("/position/longitude-deg", true);
+  _latitudeDeg = fgGetNode("/position/latitude-deg", true);
+  
+  SGPath zone(globals->get_fg_root());
+  zone.append("Timezone");
+  double lon = _longitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS;
+  double lat = _latitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS;
+  _impl = new SGTime(lon, lat, zone.str(), _timeOverride->getLongValue());
+  
+  globals->set_warp_delta(0);
+  
+  globals->get_event_mgr()->addTask("updateLocalTime", this,
+                            &TimeManager::updateLocalTime, 30*60 );
+  updateLocalTime();
+  
+  _impl->update(lon, lat, _timeOverride->getLongValue(),
+               globals->get_warp());
+  globals->set_time_params(_impl);
+  
+  initTimeOffset();
+  
+// frame/update-rate counters
+  _frameRate = fgGetNode("/sim/frame-rate", true);
+  _lastFrameTime = _impl->get_cur_time();
+  _frameCount = 0;
+}
+
+void TimeManager::postinit()
+{
+  initTimeOffset();
+}
+
+void TimeManager::reinit()
+{
+  globals->set_time_params(NULL);
+  delete _impl;
+  _inited = false;
+  globals->get_event_mgr()->removeTask("updateLocalTime");
+  
+  init();
+  postinit();
+}
+
+void TimeManager::computeTimeDeltas(double& simDt, double& realDt)
+{
+  // Update the elapsed time.
+  if (_firstUpdate) {
+    _lastStamp.stamp();
+    _firstUpdate = false;
+    _lastClockFreeze = _clockFreeze->getBoolValue();
+  }
+
+  bool scenery_loaded = fgGetBool("sim/sceneryloaded");
+  bool wait_for_scenery = !(scenery_loaded || fgGetBool("sim/sceneryloaded-override"));
+  
+  if (!wait_for_scenery) {
+    throttleUpdateRate();
+  }
+  
+  SGTimeStamp currentStamp;
+  currentStamp.stamp();
+  double dt = (currentStamp - _lastStamp).toSecs();
+  
+// Limit the time we need to spend in simulation loops
+// That means, if the /sim/max-simtime-per-frame value is strictly positive
+// you can limit the maximum amount of time you will do simulations for
+// one frame to display. The cpu time spent in simulations code is roughly
+// at least O(real_delta_time_sec). If this is (due to running debug
+// builds or valgrind or something different blowing up execution times)
+// larger than the real time you will no longer get any response
+// from flightgear. This limits that effect. Just set to property from
+// your .fgfsrc or commandline ...
+  double dtMax = _maxDtPerFrame->getDoubleValue();
+  if (0 < dtMax && dtMax < dt) {
+    dt = dtMax;
+  }
+  
+  int model_hz = fgGetInt("/sim/model-hz");
+  
+  SGSubsystemGroup* fdmGroup = 
+    globals->get_subsystem_mgr()->get_group(SGSubsystemMgr::FDM);
+  fdmGroup->set_fixed_update_time(1.0 / model_hz);
+  
+// round the real time down to a multiple of 1/model-hz.
+// this way all systems are updated the _same_ amount of dt.
+  dt += _dtRemainder;
+  int multiLoop = long(floor(dt * model_hz));
+  multiLoop = SGMisc<long>::max(0, multiLoop);
+  _dtRemainder = dt - double(multiLoop)/double(model_hz);
+  dt = double(multiLoop)/double(model_hz);
+
+  realDt = dt;
+  if (_clockFreeze->getBoolValue() || wait_for_scenery) {
+    simDt = 0;
+  } else {
+    simDt = dt;
+  }
+  
+  _lastStamp = currentStamp;
+  globals->inc_sim_time_sec(simDt);
+
+// These are useful, especially for Nasal scripts.
+  fgSetDouble("/sim/time/delta-realtime-sec", realDt);
+  fgSetDouble("/sim/time/delta-sec", simDt);
+}
+
+void TimeManager::update(double dt)
+{
+  bool freeze = _clockFreeze->getBoolValue();
+  if (freeze) {
+    // clock freeze requested
+    if (_timeOverride->getLongValue() == 0) {
+      fgSetLong( "/sim/time/cur-time-override", _impl->get_cur_time());
+      globals->set_warp(0);
+    }
+  } else {
+    // no clock freeze requested
+    if (_lastClockFreeze) {
+    // clock just unfroze, let's set warp as the difference
+    // between frozen time and current time so we don't get a
+    // time jump (and corresponding sky object and lighting
+    // jump.)
+      globals->set_warp(_timeOverride->getLongValue() - time(NULL));
+      fgSetLong( "/sim/time/cur-time-override", 0 );
+    }
+    
+    if ( globals->get_warp_delta() != 0 ) {
+      globals->inc_warp( globals->get_warp_delta() );
+    }
+  }
+
+  _lastClockFreeze = freeze;
+  double lon = _longitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS;
+  double lat = _latitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS;
+  _impl->update(lon, lat,
+               _timeOverride->getLongValue(),
+               globals->get_warp());
+
+  computeFrameRate();
+}
+
+void TimeManager::computeFrameRate()
+{
+  // Calculate frame rate average
+  if ((_impl->get_cur_time() != _lastFrameTime) && (_lastFrameTime > 0)) {
+    _frameRate->setIntValue(_frameCount);
+    _frameCount = 0;
+  }
+  
+  _lastFrameTime = _impl->get_cur_time();
+  ++_frameCount;
+}
+
+void TimeManager::throttleUpdateRate()
+{
+  double throttle_hz = fgGetDouble("/sim/frame-rate-throttle-hz", 0.0);
+  SGTimeStamp currentStamp;
+  
+  // common case, no throttle requested
+  if (throttle_hz <= 0.0) {
+    return; // no-op
+  }
+  
+  double frame_us = 1000000.0 / throttle_hz;
+#define FG_SLEEP_BASED_TIMING 1
+#if defined(FG_SLEEP_BASED_TIMING)
+  // sleep based timing loop.
+  //
+  // Calling sleep, even usleep() on linux is less accurate than
+  // we like, but it does free up the cpu for other tasks during
+  // the sleep so it is desirable.  Because of the way sleep()
+  // is implemented in consumer operating systems like windows
+  // and linux, you almost always sleep a little longer than the
+  // requested amount.
+  //
+  // To combat the problem of sleeping too long, we calculate the
+  // desired wait time and shorten it by 2000us (2ms) to avoid
+  // [hopefully] over-sleep'ing.  The 2ms value was arrived at
+  // via experimentation.  We follow this up at the end with a
+  // simple busy-wait loop to get the final pause timing exactly
+  // right.
+  //
+  // Assuming we don't oversleep by more than 2000us, this
+  // should be a reasonable compromise between sleep based
+  // waiting, and busy waiting.
+
+  // sleep() will always overshoot by a bit so undersleep by
+  // 2000us in the hopes of never oversleeping.
+  frame_us -= 2000.0;
+  if ( frame_us < 0.0 ) {
+      frame_us = 0.0;
+  }
+  
+  currentStamp.stamp();
+
+  double elapsed_us = (currentStamp - _lastStamp).toUSecs();
+  if ( elapsed_us < frame_us ) {
+    double requested_us = frame_us - elapsed_us;
+#ifdef _WIN32
+    Sleep ((int)(requested_us / 1000.0)) ;
+#else
+    usleep(requested_us) ;
+#endif
+  }
+#endif
+
+  // busy wait timing loop.
+  //
+  // This yields the most accurate timing.  If the previous
+  // ulMilliSecondSleep() call is omitted this will peg the cpu
+  // (which is just fine if FG is the only app you care about.)
+  currentStamp.stamp();
+  SGTimeStamp next_time_stamp = _lastStamp;
+  next_time_stamp += SGTimeStamp::fromSec(1e-6*frame_us);
+  while ( currentStamp < next_time_stamp ) {
+      currentStamp.stamp();
+  }
+}
+
+// periodic time updater wrapper
+void TimeManager::updateLocalTime() 
+{
+  SGPath zone(globals->get_fg_root());
+  zone.append("Timezone");
+  
+  double lon = _longitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS;
+  double lat = _latitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS;
+  
+  SG_LOG(SG_GENERAL, SG_INFO, "updateLocal(" << lon << ", " << lat << ", " << zone.str() << ")");
+  _impl->updateLocal(lon, lat, zone.str());
+}
+
+void TimeManager::initTimeOffset()
+{
+  // Handle potential user specified time offsets
+  int orig_warp = globals->get_warp();
+  time_t cur_time = _impl->get_cur_time();
+  time_t currGMT = sgTimeGetGMT( gmtime(&cur_time) );
+  time_t systemLocalTime = sgTimeGetGMT( localtime(&cur_time) );
+  time_t aircraftLocalTime = 
+      sgTimeGetGMT( fgLocaltime(&cur_time, _impl->get_zonename() ) );
+    
+  // Okay, we now have several possible scenarios
+  int offset = fgGetInt("/sim/startup/time-offset");
+  string offset_type = fgGetString("/sim/startup/time-offset-type");
+  double lon = _longitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS;
+  double lat = _latitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS;
+  int warp = 0;
+  
+  if ( offset_type == "real" ) {
+      warp = 0;
+  } else if ( offset_type == "dawn" ) {
+      warp = fgTimeSecondsUntilSunAngle( cur_time, lon, lat, 90.0, true ); 
+  } else if ( offset_type == "morning" ) {
+     warp = fgTimeSecondsUntilSunAngle( cur_time, lon, lat, 75.0, true ); 
+  } else if ( offset_type == "noon" ) {
+     warp = fgTimeSecondsUntilSunAngle( cur_time, lon, lat, 0.0, true ); 
+  } else if ( offset_type == "afternoon" ) {
+    warp = fgTimeSecondsUntilSunAngle( cur_time, lon, lat, 60.0, false );  
+  } else if ( offset_type == "dusk" ) {
+    warp = fgTimeSecondsUntilSunAngle( cur_time, lon, lat, 90.0, false );
+  } else if ( offset_type == "evening" ) {
+    warp = fgTimeSecondsUntilSunAngle( cur_time, lon, lat, 100.0, false );
+  } else if ( offset_type == "midnight" ) {
+    warp = fgTimeSecondsUntilSunAngle( cur_time, lon, lat, 180.0, false );
+  } else if ( offset_type == "system-offset" ) {
+    warp = offset;
+    orig_warp = 0;
+  } else if ( offset_type == "gmt-offset" ) {
+    warp = offset - (currGMT - systemLocalTime);
+    orig_warp = 0;
+  } else if ( offset_type == "latitude-offset" ) {
+    warp = offset - (aircraftLocalTime - systemLocalTime);
+    orig_warp = 0;
+  } else if ( offset_type == "system" ) {
+    warp = offset - (systemLocalTime - currGMT) - cur_time;
+  } else if ( offset_type == "gmt" ) {
+      warp = offset - cur_time;
+  } else if ( offset_type == "latitude" ) {
+      warp = offset - (aircraftLocalTime - currGMT)- cur_time; 
+  } else {
+    SG_LOG( SG_GENERAL, SG_ALERT,
+          "TimeManager::initTimeOffset: unsupported offset: " << offset_type );
+     warp = 0;
+  }
+  
+  globals->set_warp( orig_warp + warp );
+  _impl->update(lon, lat, _timeOverride->getLongValue(),
+               globals->get_warp() );
+
+  SG_LOG( SG_GENERAL, SG_INFO, "After fgInitTimeOffset(): warp = " 
+            << globals->get_warp() );
+}
diff --git a/src/Time/TimeManager.hxx b/src/Time/TimeManager.hxx
new file mode 100644 (file)
index 0000000..c0a89c3
--- /dev/null
@@ -0,0 +1,78 @@
+// TimeManager.hxx -- simulation-wide time management
+//
+// Written by James Turner, started July 2010.
+//
+// Copyright (C) 2010  Curtis L. Olson  - http://www.flightgear.org/~curt
+//
+// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef FG_TIME_TIMEMANAGER_HXX
+#define FG_TIME_TIMEMANAGER_HXX
+
+#include <simgear/structure/subsystem_mgr.hxx>
+
+// forward decls
+class SGTime;
+
+class TimeManager : public SGSubsystem
+{
+public:
+  TimeManager();
+  
+  void computeTimeDeltas(double& simDt, double& realDt);
+  
+  virtual void init();
+  virtual void reinit();
+  virtual void postinit();
+  
+  void update(double dt);
+  
+private:
+  /**
+   * Ensure a consistent update-rate using a combination of
+   * sleep()-ing and busy-waiting.  
+   */
+  void throttleUpdateRate();
+  
+  /**
+   * Compute frame (update) rate and write it to a property
+   */
+  void computeFrameRate();
+  
+  void updateLocalTime();
+  
+  // set up a time offset (aka warp) if one is specified
+  void initTimeOffset();
+  
+  bool _inited;
+  SGTime* _impl;
+  SGTimeStamp _lastStamp;
+  bool _firstUpdate;
+  double _dtRemainder;
+  SGPropertyNode_ptr _maxDtPerFrame;
+  SGPropertyNode_ptr _clockFreeze;
+  SGPropertyNode_ptr _timeOverride;
+  bool _lastClockFreeze;
+
+  SGPropertyNode_ptr _longitudeDeg;
+  SGPropertyNode_ptr _latitudeDeg;
+  
+// frame-rate / update-rate counters  
+  SGPropertyNode_ptr _frameRate;
+  time_t _lastFrameTime;
+  int _frameCount;
+};
+
+#endif // of FG_TIME_TIMEMANAGER_HXX
index 2145f0845188d899d51e511c257c2506eb4ba062..08d0fbf72280ef2d5f3efbd97a546e86cbe81075 100644 (file)
@@ -36,6 +36,8 @@
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/scene/sky/sky.hxx>
 #include <simgear/screen/colors.hxx>
+#include <simgear/timing/sg_time.hxx>
+#include <simgear/structure/event_mgr.hxx>
 
 #include <Main/main.hxx>
 #include <Main/globals.hxx>
 #include <Main/viewer.hxx>
 
 #include "light.hxx"
-#include "tmp.hxx"
+#include "sunsolver.hxx"
+
+/**
+ * Map i.e. project a vector onto a plane.
+ * @param normal (in) normal vector for the plane
+ * @param v0 (in) a point on the plane
+ * @param vec (in) the vector to map onto the plane
+ */
+static SGVec3f map_vec_onto_cur_surface_plane(const SGVec3f& normal, 
+                                             const SGVec3f& v0, 
+                                             const SGVec3f& vec)
+{
+    // calculate a vector "u1" representing the shortest distance from
+    // the plane specified by normal and v0 to a point specified by
+    // "vec".  "u1" represents both the direction and magnitude of
+    // this desired distance.
+
+    // u1 = ( (normal <dot> vec) / (normal <dot> normal) ) * normal
+    SGVec3f u1 = (dot(normal, vec) / dot(normal, normal)) * normal;
+
+    // calculate the vector "v" which is the vector "vec" mapped onto
+    // the plane specified by "normal" and "v0".
+
+    // v = v0 + vec - u1
+    SGVec3f v = v0 + vec - u1;
+    
+    // Calculate the vector "result" which is "v" - "v0" which is a
+    // directional vector pointing from v0 towards v
+
+    // result = v - v0
+    return v - v0;
+}
 
 
 // Constructor
@@ -114,6 +147,9 @@ void FGLight::init () {
     SGPath sky_path = path;
     sky_path.append( "Lighting/sky" );
     _sky_tbl = new SGInterpTable( sky_path.str() );
+    
+    globals->get_event_mgr()->addTask("updateSunPos", this,
+                            &FGLight::updateSunPos, 0.5 );
 }
 
 
@@ -128,8 +164,7 @@ void FGLight::reinit () {
 
     init();
 
-    fgUpdateSunPos();
-
+    updateSunPos();
     update_sky_color();
     update_adj_fog_color();
 }
@@ -188,18 +223,12 @@ void FGLight::unbind () {
 
 
 // update lighting parameters based on current sun position
-void FGLight::update( double dt ) {
-
-    _dt_total += dt;
-    if (_dt_total >= 0.5) {
-        _dt_total -= 0.5;
-        fgUpdateSunPos();
-    }
-
+void FGLight::update( double dt )
+{
     update_adj_fog_color();
 
     if (_prev_sun_angle != _sun_angle) {
-       _prev_sun_angle = _sun_angle;
+        _prev_sun_angle = _sun_angle;
         update_sky_color();
     }
 }
@@ -382,3 +411,101 @@ void FGLight::update_adj_fog_color () {
     gamma_correct_rgb( _sky_color.data(), gamma );
 }
 
+// update the cur_time_params structure with the current sun position
+void FGLight::updateSunPos()
+{
+    SGTime *t = globals->get_time_params();
+    FGViewer *v = globals->get_current_view();
+
+    SG_LOG( SG_EVENT, SG_DEBUG, "  Updating Sun position" );
+    SG_LOG( SG_EVENT, SG_DEBUG, "  Gst = " << t->getGst() );
+
+    double sun_l;
+    double sun_gd_lat;
+    fgSunPositionGST(t->getGst(), &sun_l, &sun_gd_lat);
+    set_sun_lon(sun_l);
+    set_sun_lat(sun_gd_lat);
+    SGVec3d sunpos(SGVec3d::fromGeod(SGGeod::fromRad(sun_l, sun_gd_lat)));
+
+    SG_LOG( SG_EVENT, SG_DEBUG, "    t->cur_time = " << t->get_cur_time() );
+    SG_LOG( SG_EVENT, SG_DEBUG,
+            "    Sun Geodetic lat = " << sun_gd_lat
+            << " Geodetic lat = " << sun_gd_lat );
+
+    // update the sun light vector
+    sun_vec() = SGVec4f(toVec3f(normalize(sunpos)), 0);
+    sun_vec_inv() = - sun_vec();
+
+    // calculate the sun's relative angle to local up
+    SGVec3d viewPos = v->get_view_pos();
+    SGQuatd hlOr = SGQuatd::fromLonLat(SGGeod::fromCart(viewPos));
+    SGVec3f world_up = toVec3f(hlOr.backTransform(-SGVec3d::e3()));
+    SGVec3f nsun = toVec3f(normalize(sunpos));
+    // cout << "nup = " << nup[0] << "," << nup[1] << ","
+    //      << nup[2] << endl;
+    // cout << "nsun = " << nsun[0] << "," << nsun[1] << ","
+    //      << nsun[2] << endl;
+
+    set_sun_angle( acos( dot ( world_up, nsun ) ) );
+    SG_LOG( SG_EVENT, SG_DEBUG, "sun angle relative to current location = "
+            << get_sun_angle() );
+
+    // calculate vector to sun's position on the earth's surface
+    SGVec3d rel_sunpos = sunpos - v->get_view_pos();
+    // vector in cartesian coordinates from current position to the
+    // postion on the earth's surface the sun is directly over
+    SGVec3f to_sun = toVec3f(rel_sunpos);
+    // printf( "Vector to sun = %.2f %.2f %.2f\n",
+    //         v->to_sun[0], v->to_sun[1], v->to_sun[2]);
+
+    // Given a vector from the view position to the point on the
+    // earth's surface the sun is directly over, map into onto the
+    // local plane representing "horizontal".
+
+    // surface direction to go to head towards sun
+    SGVec3f surface_to_sun;
+    SGVec3f view_pos = toVec3f(v->get_view_pos());
+    surface_to_sun = map_vec_onto_cur_surface_plane(world_up, view_pos, to_sun);
+    surface_to_sun = normalize(surface_to_sun);
+    // cout << "(sg) Surface direction to sun is "
+    //   << surface_to_sun[0] << ","
+    //   << surface_to_sun[1] << ","
+    //   << surface_to_sun[2] << endl;
+    // cout << "Should be close to zero = "
+    //   << sgScalarProductVec3(nup, surface_to_sun) << endl;
+
+    // calculate the angle between surface_to_sun and
+    // v->get_surface_east().  We do this so we can sort out the
+    // acos() ambiguity.  I wish I could think of a more efficient
+    // way. :-(
+    SGVec3f surface_east(toVec3f(hlOr.backTransform(SGVec3d::e2())));
+    float east_dot = dot( surface_to_sun, surface_east );
+    // cout << "  East dot product = " << east_dot << endl;
+
+    // calculate the angle between v->surface_to_sun and
+    // v->surface_south.  this is how much we have to rotate the sky
+    // for it to align with the sun
+    SGVec3f surface_south(toVec3f(hlOr.backTransform(-SGVec3d::e1())));
+    float dot_ = dot( surface_to_sun, surface_south );
+    // cout << "  Dot product = " << dot << endl;
+
+    if (dot_ > 1.0) {
+        SG_LOG( SG_ASTRO, SG_INFO,
+                "Dot product  = " << dot_ << " is greater than 1.0" );
+        dot_ = 1.0;
+    }
+    else if (dot_ < -1.0) {
+         SG_LOG( SG_ASTRO, SG_INFO,
+                 "Dot product  = " << dot_ << " is less than -1.0" );
+         dot_ = -1.0;
+     }
+
+    if ( east_dot >= 0 ) {
+        set_sun_rotation( acos(dot_) );
+    } else {
+        set_sun_rotation( -acos(dot_) );
+    }
+    // cout << "  Sky needs to rotate = " << angle << " rads = "
+    //      << angle * SGD_RADIANS_TO_DEGREES << " degrees." << endl;
+
+}
index f3ecb32e16bf5f8f8c30c23ca2435ca6c36e38f3..ebc5099665cd117b6bc0c94deee0249eda2e9329 100644 (file)
@@ -102,6 +102,8 @@ private:
     void update_sky_color ();
     void update_adj_fog_color ();
 
+    void updateSunPos();
+    
     // properties for chrome light; not a tie because I want to fire
     // property listeners when the values change.
     SGPropertyNode_ptr _chromeProps[4];
index 2275f99024c647ded6132a50db93b67d9e6a991d..a83422759ef9bfcbe8252d76bc88f2b8ec6eb9a8 100644 (file)
@@ -37,7 +37,6 @@
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
 
-#include "tmp.hxx"
 #include "sunsolver.hxx"
 
 
diff --git a/src/Time/tmp.cxx b/src/Time/tmp.cxx
deleted file mode 100644 (file)
index 3b3ae2a..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-// tmp.cxx -- stuff I don't know what to do with at the moment
-//
-// Written by Curtis Olson, started July 2000.
-//
-// Copyright (C) 2000  Curtis L. Olson  - http://www.flightgear.org/~curt
-//
-// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// $Id$
-
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <simgear/math/SGMath.hxx>
-#include <simgear/misc/sg_path.hxx>
-#include <simgear/timing/sg_time.hxx>
-
-#include <Main/fg_props.hxx>
-#include <Main/globals.hxx>
-#include <Main/viewer.hxx>
-#include <Scenery/scenery.hxx>
-
-#include "light.hxx"
-#include "sunsolver.hxx"
-#include "tmp.hxx"
-
-/**
- * Map i.e. project a vector onto a plane.
- * @param normal (in) normal vector for the plane
- * @param v0 (in) a point on the plane
- * @param vec (in) the vector to map onto the plane
- */
-static SGVec3f map_vec_onto_cur_surface_plane(const SGVec3f& normal, 
-                                             const SGVec3f& v0, 
-                                             const SGVec3f& vec)
-{
-    // calculate a vector "u1" representing the shortest distance from
-    // the plane specified by normal and v0 to a point specified by
-    // "vec".  "u1" represents both the direction and magnitude of
-    // this desired distance.
-
-    // u1 = ( (normal <dot> vec) / (normal <dot> normal) ) * normal
-    SGVec3f u1 = (dot(normal, vec) / dot(normal, normal)) * normal;
-
-    // calculate the vector "v" which is the vector "vec" mapped onto
-    // the plane specified by "normal" and "v0".
-
-    // v = v0 + vec - u1
-    SGVec3f v = v0 + vec - u1;
-    
-    // Calculate the vector "result" which is "v" - "v0" which is a
-    // directional vector pointing from v0 towards v
-
-    // result = v - v0
-    return v - v0;
-}
-
-
-// periodic time updater wrapper
-void fgUpdateLocalTime() {
-    static const SGPropertyNode *longitude
-       = fgGetNode("/position/longitude-deg");
-    static const SGPropertyNode *latitude
-       = fgGetNode("/position/latitude-deg");
-
-    SGPath zone( globals->get_fg_root() );
-    zone.append( "Timezone" );
-
-    SG_LOG(SG_GENERAL, SG_INFO, "updateLocal("
-          << longitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS
-          << ", "
-          << latitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS
-          << ", " << zone.str() << ")");
-    globals->get_time_params()->updateLocal( longitude->getDoubleValue()
-                                              * SGD_DEGREES_TO_RADIANS, 
-                                            latitude->getDoubleValue()
-                                              * SGD_DEGREES_TO_RADIANS,
-                                            zone.str() );
-}
-
-
-// update the cur_time_params structure with the current sun position
-void fgUpdateSunPos( void ) {
-#if 0
-    // This only works at lat,lon = 0,0
-    // need to find a way to get it working at other locations
-
-    FGLight *light = (FGLight *)(globals->get_subsystem("lighting"));
-    FGViewer *viewer = globals->get_current_view();
-    SGTime *time_now = globals->get_time_params();
-
-    SG_LOG( SG_EVENT, SG_DEBUG, "  Updating Sun position" );
-    SG_LOG( SG_EVENT, SG_DEBUG, "  Gst = " << time_now->getGst() );
-
-    double sun_lon, sun_lat;
-    fgSunPositionGST(time_now->getGst(), &sun_lon, &sun_lat);
-    light->set_sun_lon(sun_lon);
-    light->set_sun_lat(sun_lat);
-
-    // update the sun light vector
-    // calculations are in the horizontal normal plane: x-north, y-east, z-down
-    static SGQuatd q = SGQuatd::fromLonLat(SGGeod::fromRad(0,0));
-
-    // sun orientation
-    SGGeod geodSunPos = SGGeod::fromRad(sun_lon, sun_lat);
-    SGQuatd sunOr = SGQuatd::fromLonLat(geodSunPos);
-
-    // scenery orientation
-    SGGeod geodViewPos = SGGeod::fromCart(viewer->getViewPosition());
-    SGQuatd hlOr = SGQuatd::fromLonLat(geodViewPos);
-    SGVec3d localAt = hlOr.backTransform(SGVec3d::e3());
-
-    // transpose the sun direction from (lat,lon) to (0,0)
-    SGVec3d transSunDir = (q*sunOr).transform(-localAt);
-    SGQuatd sunDirOr = SGQuatd::fromRealImag(0, transSunDir);
-
-    // transpose the calculated sun vector back to (lat,lon)
-    SGVec3d sunDirection = sunDirOr.transform(localAt);
-    light->set_sun_rotation( acos(sunDirection[1])-SGD_PI_2 );
-    light->set_sun_angle( acos(-sunDirection[2]) );
-
-    SGVec3d sunPos = SGVec3d::fromGeod(geodSunPos);
-    light->sun_vec() = SGVec4f(toVec3f(normalize(sunPos)), 0);
-    light->sun_vec_inv() = -light->sun_vec();
-
-#else
-    FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
-    SGTime *t = globals->get_time_params();
-    FGViewer *v = globals->get_current_view();
-
-    SG_LOG( SG_EVENT, SG_DEBUG, "  Updating Sun position" );
-    SG_LOG( SG_EVENT, SG_DEBUG, "  Gst = " << t->getGst() );
-
-    double sun_l;
-    double sun_gd_lat;
-    fgSunPositionGST(t->getGst(), &sun_l, &sun_gd_lat);
-    l->set_sun_lon(sun_l);
-    l->set_sun_lat(sun_gd_lat);
-    SGVec3d sunpos(SGVec3d::fromGeod(SGGeod::fromRad(sun_l, sun_gd_lat)));
-
-    SG_LOG( SG_EVENT, SG_DEBUG, "    t->cur_time = " << t->get_cur_time() );
-    SG_LOG( SG_EVENT, SG_DEBUG,
-            "    Sun Geodetic lat = " << sun_gd_lat
-            << " Geodetic lat = " << sun_gd_lat );
-
-    // update the sun light vector
-    l->sun_vec() = SGVec4f(toVec3f(normalize(sunpos)), 0);
-    l->sun_vec_inv() = - l->sun_vec();
-
-    // calculate the sun's relative angle to local up
-    SGVec3d viewPos = v->get_view_pos();
-    SGQuatd hlOr = SGQuatd::fromLonLat(SGGeod::fromCart(viewPos));
-    SGVec3f world_up = toVec3f(hlOr.backTransform(-SGVec3d::e3()));
-    SGVec3f nsun = toVec3f(normalize(sunpos));
-    // cout << "nup = " << nup[0] << "," << nup[1] << ","
-    //      << nup[2] << endl;
-    // cout << "nsun = " << nsun[0] << "," << nsun[1] << ","
-    //      << nsun[2] << endl;
-
-    l->set_sun_angle( acos( dot ( world_up, nsun ) ) );
-    SG_LOG( SG_EVENT, SG_DEBUG, "sun angle relative to current location = "
-            << l->get_sun_angle() );
-
-    // calculate vector to sun's position on the earth's surface
-    SGVec3d rel_sunpos = sunpos - v->get_view_pos();
-    // vector in cartesian coordinates from current position to the
-    // postion on the earth's surface the sun is directly over
-    SGVec3f to_sun = toVec3f(rel_sunpos);
-    // printf( "Vector to sun = %.2f %.2f %.2f\n",
-    //         v->to_sun[0], v->to_sun[1], v->to_sun[2]);
-
-    // Given a vector from the view position to the point on the
-    // earth's surface the sun is directly over, map into onto the
-    // local plane representing "horizontal".
-
-    // surface direction to go to head towards sun
-    SGVec3f view_pos = toVec3f(v->get_view_pos());
-    SGVec3f surface_to_sun = map_vec_onto_cur_surface_plane(world_up, view_pos, to_sun);
-    
-    surface_to_sun = normalize(surface_to_sun);
-    // cout << "(sg) Surface direction to sun is "
-    //   << surface_to_sun[0] << ","
-    //   << surface_to_sun[1] << ","
-    //   << surface_to_sun[2] << endl;
-    // cout << "Should be close to zero = "
-    //   << sgScalarProductVec3(nup, surface_to_sun) << endl;
-
-    // calculate the angle between surface_to_sun and
-    // v->get_surface_east().  We do this so we can sort out the
-    // acos() ambiguity.  I wish I could think of a more efficient
-    // way. :-(
-    SGVec3f surface_east(toVec3f(hlOr.backTransform(SGVec3d::e2())));
-    float east_dot = dot( surface_to_sun, surface_east );
-    // cout << "  East dot product = " << east_dot << endl;
-
-    // calculate the angle between v->surface_to_sun and
-    // v->surface_south.  this is how much we have to rotate the sky
-    // for it to align with the sun
-    SGVec3f surface_south(toVec3f(hlOr.backTransform(-SGVec3d::e1())));
-    float dot_ = dot( surface_to_sun, surface_south );
-    // cout << "  Dot product = " << dot << endl;
-
-    if (dot_ > 1.0) {
-        SG_LOG( SG_ASTRO, SG_INFO,
-                "Dot product  = " << dot_ << " is greater than 1.0" );
-        dot_ = 1.0;
-    }
-    else if (dot_ < -1.0) {
-         SG_LOG( SG_ASTRO, SG_INFO,
-                 "Dot product  = " << dot_ << " is less than -1.0" );
-         dot_ = -1.0;
-     }
-
-    if ( east_dot >= 0 ) {
-        l->set_sun_rotation( acos(dot_) );
-    } else {
-        l->set_sun_rotation( -acos(dot_) );
-    }
-    // cout << "  Sky needs to rotate = " << angle << " rads = "
-    //      << angle * SGD_RADIANS_TO_DEGREES << " degrees." << endl;
-
-#endif
-}
-
diff --git a/src/Time/tmp.hxx b/src/Time/tmp.hxx
deleted file mode 100644 (file)
index 0d65655..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-// tmp.hxx -- stuff I don't know what to do with at the moment
-//
-// Written by Curtis Olson, started July 2000.
-//
-// Copyright (C) 2000  Curtis L. Olson  - http://www.flightgear.org/~curt
-//
-// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// $Id$
-
-
-#ifndef _TMP_HXX
-#define _TMP_HXX
-
-
-#ifndef __cplusplus                                                          
-# error This library requires C++
-#endif                                   
-
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-
-// periodic time updater
-void fgUpdateLocalTime();
-
-// update the cur_time_params structure with the current sun position
-void fgUpdateSunPos( void );
-
-#endif // _LIGHT_HXX
-