]> git.mxchange.org Git - flightgear.git/commitdiff
Revert "Create TimeManager subsystem" - not quite ready for prime-time yet!
authorJames Turner <zakalawe@mac.com>
Sun, 1 Aug 2010 23:23:36 +0000 (00:23 +0100)
committerJames Turner <zakalawe@mac.com>
Sun, 1 Aug 2010 23:23:36 +0000 (00:23 +0100)
This reverts commit 50eb95dcadaf39d892212f2c5c6fe2459b190719.

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 [deleted file]
src/Time/TimeManager.hxx [deleted file]
src/Time/light.cxx
src/Time/light.hxx
src/Time/sunsolver.cxx
src/Time/tmp.cxx [new file with mode: 0644]
src/Time/tmp.hxx [new file with mode: 0644]

index eacb7a081dc0317f94ed2c0f929dedec049cf964..9bf22509d9d275ba17b96e1d4cfbaea5275fb4c4 100644 (file)
                                >
                        </File>
                        <File
-                               RelativePath="..\..\..\src\Time\TimeManager.cxx"
+                               RelativePath="..\..\..\src\Time\tmp.cxx"
                                >
                        </File>
                        <File
-                               RelativePath="..\..\..\src\Time\TimeManager.hxx"
+                               RelativePath="..\..\..\src\Time\tmp.hxx"
                                >
                        </File>
                </Filter>
index c277b6b73a4bd259636b8b81bf033768a4ee1cc1..1dd37d387e8912f2e11cc24a4f6643994c1c74e3 100644 (file)
@@ -37,6 +37,7 @@
 #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 36c5a17ffa23ef425c4769b3909a0e2d6a6b84b7..7805ac413c6950c8e111a63824a818080825a37f 100644 (file)
@@ -62,6 +62,8 @@
 #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>
@@ -1268,6 +1272,140 @@ 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.
@@ -1390,6 +1528,17 @@ 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.
     ////////////////////////////////////////////////////////////////////
@@ -1565,7 +1714,10 @@ void fgReInitSubsystems()
 
     globals->get_controls()->reset_all();
 
-    globals->get_subsystem("time")->reinit();
+    fgUpdateLocalTime();
+
+    // re-init to proper time of day setting
+    fgInitTimeOffset();
 
     if ( !freeze ) {
         fgSetBool("/sim/freeze/master", false);
@@ -1591,6 +1743,11 @@ 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 256716a8800eda171de5f0c636eb9647d45cbfb3..da68ab2e22fabb52546007897d5ddcceca4817ab 100644 (file)
@@ -79,6 +79,14 @@ 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 935bdd9cd0ab08c3f619292cca519591e506230a..789d80ce885eaa6ce54a3dde72d6920b6e6d1663 100644 (file)
@@ -34,6 +34,8 @@
 
 #include <iostream>
 
+#include <plib/netSocket.h>
+
 #include <osg/Camera>
 #include <osg/GraphicsContext>
 #include <osgDB/Registry>
@@ -65,7 +67,7 @@
 #include <Sound/fg_fx.hxx>
 #include <ATCDCL/ATCmgr.hxx>
 #include <ATCDCL/AIMgr.hxx>
-#include <Time/TimeManager.hxx>
+#include <Time/tmp.hxx>
 #include <Environment/environment_mgr.hxx>
 #include <Environment/ephemeris.hxx>
 #include <GUI/new_gui.hxx>
@@ -83,6 +85,8 @@
 #include "WindowSystemAdapter.hxx"
 #include <Main/viewer.hxx>
 
+static double real_delta_time_sec = 0.0;
+double delta_time_sec = 0.0;
 
 using namespace flightgear;
 
@@ -95,7 +99,10 @@ 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 *);
@@ -107,7 +114,8 @@ 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
@@ -120,24 +128,172 @@ 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"
-    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);
-    
+
+    // 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() );
+
     if (globals->get_warp_delta() != 0) {
         FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
         l->update( 0.5 );
@@ -151,6 +307,36 @@ 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
@@ -159,7 +345,7 @@ static void fgMainLoop( void ) {
 #if ENABLE_ATCDCL  
     // Run ATC subsystem
     if (fgGetBool("/sim/atc/enabled"))
-        globals->get_ATC_mgr()->update(sim_dt);
+        globals->get_ATC_mgr()->update(delta_time_sec);
 
 
     // Run the AI subsystem
@@ -170,11 +356,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(sim_dt);
+        globals->get_AI_mgr()->update(delta_time_sec);
 #endif  
     
-    globals->get_subsystem_mgr()->update(sim_dt);
-    globals->get_aircraft_model()->update(sim_dt);
+    globals->get_subsystem_mgr()->update(delta_time_sec);
+    globals->get_aircraft_model()->update(delta_time_sec);
     
     //
     // Tile Manager updates - see if we need to load any new scenery tiles.
@@ -190,14 +376,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(sim_dt);
+    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(sim_dt);
+    globals->get_model_mgr()->update(delta_time_sec);
 
     // update the view angle as late as possible, but before sound calculations
-    globals->get_viewmgr()->update(real_dt);
+    globals->get_viewmgr()->update(real_delta_time_sec);
 
     // 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-
@@ -233,13 +419,13 @@ static void fgMainLoop( void ) {
         if (smgr_enabled == true) {
             static SGPropertyNode *volume = fgGetNode("/sim/sound/volume");
             smgr->set_volume(volume->getFloatValue());
-            smgr->update(sim_dt);
+            smgr->update(delta_time_sec);
         }
     }
 #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);
@@ -380,10 +566,9 @@ static void fgIdleFunction ( void ) {
         fgInitPosition();
         fgInitTowerLocationListener();
 
-        TimeManager* t = new TimeManager;
-        globals->add_subsystem("time", t, SGSubsystemMgr::INIT);
-        t->init(); // need to init now, not during initSubsystems
-        
+        SGTime *t = fgInitTime();
+        globals->set_time_params( t );
+
         // Do some quick general initializations
         if( !fgInitGeneral()) {
             SG_LOG( SG_GENERAL, SG_ALERT,
@@ -548,7 +733,10 @@ 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 2117f605b9cd2f6f7291a413f9e2457bbca3ee3a..b15846b5a9a15ec3f5234d02c294c09bf8f34d3e 100644 (file)
@@ -8,6 +8,8 @@ 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 a3d6d988651ccae043f96a605bba6274b1350cc4..3cd5a76186aee751a143066c2c5b5d4047099f42 100644 (file)
@@ -563,12 +563,16 @@ FGRenderer::init( void )
 // Update all Visuals (redraws anything graphics related)
 void
 FGRenderer::update( bool refresh_camera_settings ) {
-    bool scenery_loaded = fgGetBool("sim/sceneryloaded", false)
+    bool scenery_loaded = fgGetBool("sim/sceneryloaded")
                           || fgGetBool("sim/sceneryloaded-override");
     osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
-    if (!scenery_loaded) {
-      fgSetDouble("/sim/startup/splash-alpha", 1.0);
-      return;
+    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;
     }
 
     // Fade out the splash screen over the first three seconds.
@@ -625,7 +629,9 @@ 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, 0.0 /* time factor, now unused */);
+    thesky->modify_vis( altitude_m,
+                        ( global_multi_loop * fgGetInt("/sim/speed-up") )
+                        / (double)fgGetInt("/sim/model-hz") );
 
     // update the sky dome
     if ( skyblend ) {
@@ -667,8 +673,7 @@ 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 46fb62d1ab857710b8a594d7af24cd1ec0f29918..bc28f928a6219cc7317449c00f8abb66896947fd 100644 (file)
@@ -31,6 +31,7 @@
 #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 eaae3c32a0adbabb07b8242d5621b88d46f7616a..6ddb8349612fbd0d6929a2fa5cd85bbc05781e73 100644 (file)
@@ -30,6 +30,7 @@
 #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 5db2d7b26c68429e7e8d1c42657fc39e21994934..7c824d8d0cc85de7a4a0331986c6898f74e7b921 100644 (file)
@@ -3,6 +3,6 @@ noinst_LIBRARIES = libTime.a
 libTime_a_SOURCES = \
        light.cxx light.hxx \
        sunsolver.cxx sunsolver.hxx \
-       TimeManager.cxx TimeManager.hxx
+       tmp.cxx tmp.hxx
 
 INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
diff --git a/src/Time/TimeManager.cxx b/src/Time/TimeManager.cxx
deleted file mode 100644 (file)
index 1adfbbf..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-// 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
deleted file mode 100644 (file)
index c0a89c3..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// 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 08d0fbf72280ef2d5f3efbd97a546e86cbe81075..2145f0845188d899d51e511c257c2506eb4ba062 100644 (file)
@@ -36,8 +36,6 @@
 #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 "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;
-}
+#include "tmp.hxx"
 
 
 // Constructor
@@ -147,9 +114,6 @@ 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 );
 }
 
 
@@ -164,7 +128,8 @@ void FGLight::reinit () {
 
     init();
 
-    updateSunPos();
+    fgUpdateSunPos();
+
     update_sky_color();
     update_adj_fog_color();
 }
@@ -223,12 +188,18 @@ void FGLight::unbind () {
 
 
 // update lighting parameters based on current sun position
-void FGLight::update( double dt )
-{
+void FGLight::update( double dt ) {
+
+    _dt_total += dt;
+    if (_dt_total >= 0.5) {
+        _dt_total -= 0.5;
+        fgUpdateSunPos();
+    }
+
     update_adj_fog_color();
 
     if (_prev_sun_angle != _sun_angle) {
-        _prev_sun_angle = _sun_angle;
+       _prev_sun_angle = _sun_angle;
         update_sky_color();
     }
 }
@@ -411,101 +382,3 @@ 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 ebc5099665cd117b6bc0c94deee0249eda2e9329..f3ecb32e16bf5f8f8c30c23ca2435ca6c36e38f3 100644 (file)
@@ -102,8 +102,6 @@ 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 a83422759ef9bfcbe8252d76bc88f2b8ec6eb9a8..2275f99024c647ded6132a50db93b67d9e6a991d 100644 (file)
@@ -37,6 +37,7 @@
 #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
new file mode 100644 (file)
index 0000000..3b3ae2a
--- /dev/null
@@ -0,0 +1,238 @@
+// 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
new file mode 100644 (file)
index 0000000..0d65655
--- /dev/null
@@ -0,0 +1,45 @@
+// 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
+