]> git.mxchange.org Git - flightgear.git/blobdiff - Time/fg_time.cxx
Modifications to incorporate Jon S. Berndts flight model code.
[flightgear.git] / Time / fg_time.cxx
index 9c0510df17685c14b753bee16fef1c532fc8e298..f7a1c6e40af2f0113bb70de2e6f446eb3ce26c04 100644 (file)
 #  include <config.h>
 #endif
 
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
+#include "Include/compiler.h"
+
+#ifdef FG_HAVE_STD_INCLUDES
+#  include <cmath>
+#  include <cstdio>
+#  include <cstdlib>
+#  include <ctime>
+#else
+#  include <math.h>
+#  include <stdio.h>
+#  include <stdlib.h>
+#  include <time.h>
+#endif
 
 #ifdef HAVE_SYS_TIMEB_H
 #  include <sys/timeb.h> // for ftime() and struct timeb
 #  include <sys/time.h>  // for get/setitimer, gettimeofday, struct timeval
 #endif
 
-#include <Debug/fg_debug.h>
-#include <Flight/flight.h>
+#include <Astro/sky.hxx>
+#include <Astro/solarsystem.hxx>
+#include <Debug/logstream.hxx>
+#include <FDM/flight.hxx>
 #include <Include/fg_constants.h>
 #include <Main/options.hxx>
+#include <Time/light.hxx>
 
 #include "fg_time.hxx"
 
 #define DEGHR(x)        ((x)/15.)
 #define RADHR(x)        DEGHR(x*RAD_TO_DEG)
 
+// #define MK_TIME_IS_GMT 0         // default value
+// #define TIME_ZONE_OFFSET_WORK 0  // default value
 
-fgTIME cur_time_params;
-
-
-// Initialize the time dependent variables
-
-void fgTimeInit(fgTIME *t) {
-    fgOPTIONS *o;
 
-    o = &current_options;
-
-    fgPrintf( FG_EVENT, FG_INFO, "Initializing Time\n");
+fgTIME cur_time_params;
 
-    t->gst_diff = -9999.0;
-    fgPrintf( FG_EVENT, FG_DEBUG, "o->time_offset = %d\n", o->time_offset);
 
-    t->warp = o->time_offset;
-    t->warp_delta = 0;
+// Force an update of the sky and lighting parameters
+static void local_update_sky_and_lighting_params( void ) {
+    // fgSunInit();
+    SolarSystem::theSolarSystem->rebuild();
+    cur_light_params.Update();
+    fgSkyColorsInit();
 }
 
 
-// Portability wrap to get current time.
-void timestamp(fg_timestamp *timestamp) {
-#if defined( HAVE_GETTIMEOFDAY )
-    struct timeval current;
-    struct timezone tz;
-    // fg_timestamp currtime;
-    gettimeofday(&current, &tz);
-    timestamp->seconds = current.tv_sec;
-    timestamp->millis = current.tv_usec / 1000;
-#elif defined( HAVE_GETLOCALTIME )
-    SYSTEMTIME current;
-    GetLocalTime(&current);
-    timestamp->seconds = current.wSecond;
-    timestamp->millis = current.wMilliseconds;
-#elif defined( HAVE_FTIME )
-    struct timeb current;
-    ftime(&current);
-    timestamp->seconds = current.time;
-    timestamp->millis = current.millitm;
-#else
-# error Port me
-#endif
-}
+// Initialize the time dependent variables
+void fgTimeInit(fgTIME *t) {
+    FG_LOG( FG_EVENT, FG_INFO, "Initializing Time" );
 
+    t->gst_diff = -9999.0;
 
-// Return duration in millis from first to last
-long timediff(fg_timestamp *first, fg_timestamp *last) {
-    return 1000 * (last->seconds - first->seconds) + 
-       (last->millis - first->millis);
-}
+    FG_LOG( FG_EVENT, FG_DEBUG, 
+           "time offset = " << current_options.get_time_offset() );
 
+    t->warp = current_options.get_time_offset();
+    t->warp_delta = 0;
 
-// Return new timestamp given a time stamp and an interval to add in
-void timesum(fg_timestamp *res, fg_timestamp *start, long millis) {
-    res->seconds = start->seconds + 
-       ( start->millis + millis ) / 1000;
-    res->millis = ( start->millis + millis ) % 1000;
+    t->pause = current_options.get_pause();
 }
 
 
@@ -164,7 +147,7 @@ double cal_mjd (int mn, double dy, int yr) {
 }
 
 
-// given an mjd, return greenwich mean siderial time, gst
+// given an mjd, return greenwich mean sidereal time, gst
 
 double utc_gst (double mjd) {
     double gst;
@@ -177,7 +160,7 @@ double utc_gst (double mjd) {
     x /= 3600.0;
     gst = (1.0/SIDRATE)*hr + x;
 
-    fgPrintf( FG_EVENT, FG_DEBUG, "  gst => %.4f\n", gst);
+    FG_LOG( FG_EVENT, FG_DEBUG, "  gst => " << gst );
 
     return(gst);
 }
@@ -210,115 +193,126 @@ double sidereal_precise (double mjd, double lng) {
 }
 
 
-// return a courser but cheaper estimate of sidereal time
-double sidereal_course(struct tm *gmt, time_t now, double lng) {
-    time_t start, start_gmt;
-    struct tm mt;
-    long int offset;
-    double diff, part, days, hours, lst;
-
-    // I believe the mktime() has a SYSV vs. BSD behavior difference.
+// Fix up timezone if using ftime()
+long int fix_up_timezone( long int timezone_orig ) {
+#if !defined( HAVE_GETTIMEOFDAY ) && defined( HAVE_FTIME )
+    // ftime() needs a little extra help finding the current timezone
+    struct timeb current;
+    ftime(&current);
+    return( current.timezone * 60 );
+#else
+    return( timezone_orig );
+#endif
+}
 
-    // The BSD style mktime() is nice because it returns its result
-    // assuming you have specified the input time in GMT
 
-    // The SYSV style mktime() is a pain because it returns its result
-    // assuming you have specified the input time in your local
-    // timezone.  Therefore you have to go to extra trouble to convert
-    // back to GMT.
+// Return time_t for Sat Mar 21 12:00:00 GMT
+//
+// I believe the mktime() has a SYSV vs. BSD behavior difference.
+//
+// The BSD style mktime() is nice because it returns its result
+// assuming you have specified the input time in GMT
+//
+// The SYSV style mktime() is a pain because it returns its result
+// assuming you have specified the input time in your local timezone.
+// Therefore you have to go to extra trouble to convert back to GMT.
+//
+// If you are having problems with incorrectly positioned astronomical
+// bodies, this is a really good place to start looking.
 
-    // If you are having problems with incorrectly positioned
-    // astronomical bodies, this is a really good place to start
-    // looking.
+time_t get_start_gmt(int year) {
+    struct tm mt;
 
-#if !defined(HAVE_DAYLIGHT)
     // For now we assume that if daylight is not defined in
     // /usr/include/time.h that we have a machine with a BSD behaving
     // mktime()
-    int mktime_is_gmt = 1;
-
-    // only used for systems with SYSV style mktime() to compensate
-    // for mktime() assuming local timezone but we need to define this
-    // to keep the compiler happy
-    int daylight;
-#else
-    int mktime_is_gmt = 0;
-#endif
-
-#if !defined(HAVE_TIMEZONE)
-    // only used for systems with SYSV style mktime() to compensate
-    // for mktime() assuming local timezone but we need to define this
-    // to keep the compiler happy
-    long int timezone;
-#endif
-
-    // ftime() needs a little extra help finding the current timezone
-#if defined( HAVE_GETTIMEOFDAY )
-#elif defined( HAVE_FTIME )
-    struct timeb current;
-#else
-# error Port me
-#endif
+#   if !defined(HAVE_DAYLIGHT)
+#       define MK_TIME_IS_GMT 1
+#   endif
 
-    fgPrintf(FG_EVENT, FG_DEBUG, 
-            "  COURSE: GMT = %d/%d/%2d %d:%02d:%02d\n", 
-            gmt->tm_mon, gmt->tm_mday, gmt->tm_year,
-            gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
+    // timezone seems to work as a proper offset for Linux & Solaris
+#   if defined( __linux__ ) || defined( __sun__ ) 
+#       define TIMEZONE_OFFSET_WORKS 1
+#   endif
 
     mt.tm_mon = 2;
     mt.tm_mday = 21;
-    mt.tm_year = gmt->tm_year;
+    mt.tm_year = year;
     mt.tm_hour = 12;
     mt.tm_min = 0;
     mt.tm_sec = 0;
     mt.tm_isdst = -1; // let the system determine the proper time zone
 
-    if ( mktime_is_gmt ) {
-       start_gmt = mktime(&mt);
-    } else {
-       start = mktime(&mt);
-       daylight = mt.tm_isdst;
-
-       fgPrintf( FG_EVENT, FG_DEBUG, "start1 = %ld\n", start);
-       fgPrintf( FG_EVENT, FG_DEBUG, "start2 = %s (tm_isdst = %d)", 
-                 ctime(&start), mt.tm_isdst);
-
-       // ftime() needs a little extra help finding the current timezone
-#if defined( HAVE_GETTIMEOFDAY )
-#elif defined( HAVE_FTIME )
-       ftime(&current);
-       timezone = current.timezone * 60;
-#else
-# error Port me
-#endif
+#   if defined( MK_TIME_IS_GMT )
+    return ( mktime(&mt) );
+#   else // ! defined ( MK_TIME_IS_GMT )
 
-       if ( daylight > 0 ) {
-           daylight = 1;
-       } else if ( daylight < 0 ) {
-           fgPrintf( FG_EVENT, FG_WARN, 
-                     "OOOPS, big time problem in fg_time.c, no daylight savings info.\n");
-       }
+    long int start = mktime(&mt);
 
-       offset = -(timezone / 3600 - daylight);
+    FG_LOG( FG_EVENT, FG_DEBUG, "start1 = " << start );
+    // the ctime() call can screw up time progression on some versions
+    // of Linux
+    // fgPrintf( FG_EVENT, FG_DEBUG, "start2 = %s", ctime(&start));
+    FG_LOG( FG_EVENT, FG_DEBUG, "(tm_isdst = " << mt.tm_isdst << ")" );
 
-       fgPrintf( FG_EVENT, FG_DEBUG,
-                 "  Raw time zone offset = %ld\n", timezone);
-       fgPrintf( FG_EVENT, FG_DEBUG,
-                 "  Daylight Savings = %d\n", daylight);
-       fgPrintf( FG_EVENT, FG_DEBUG,
-                 "  Local hours from GMT = %ld\n", offset);
+    timezone = fix_up_timezone( timezone );
 
-       start_gmt = start - timezone + (daylight * 3600);
+#   if defined( TIMEZONE_OFFSET_WORKS )
+    FG_LOG( FG_EVENT, FG_DEBUG, 
+           "start = " << start << ", timezone = " << timezone );
+    return( start - timezone );
+#   else // ! defined( TIMEZONE_OFFSET_WORKS )
 
-       fgPrintf( FG_EVENT, FG_DEBUG, "  March 21 noon (CST) = %ld\n", start);
+    daylight = mt.tm_isdst;
+    if ( daylight > 0 ) {
+       daylight = 1;
+    } else if ( daylight < 0 ) {
+       FG_LOG( FG_EVENT, FG_WARN, 
+               "OOOPS, problem in fg_time.cxx, no daylight savings info." );
     }
 
-    fgPrintf( FG_EVENT, FG_DEBUG, "  March 21 noon (GMT) = %ld\n", start_gmt);
+    long int offset = -(timezone / 3600 - daylight);
+
+    FG_LOG( FG_EVENT, FG_DEBUG, "  Raw time zone offset = " << timezone );
+    FG_LOG( FG_EVENT, FG_DEBUG, "  Daylight Savings = " << daylight );
+    FG_LOG( FG_EVENT, FG_DEBUG, "  Local hours from GMT = " << offset );
+    
+    long int start_gmt = start - timezone + (daylight * 3600);
+    
+    FG_LOG( FG_EVENT, FG_DEBUG, "  March 21 noon (CST) = " << start );
+
+    return ( start_gmt );
+#   endif // ! defined( TIMEZONE_OFFSET_WORKS )
+#   endif // ! defined ( MK_TIME_IS_GMT )
+}
+
+static char*
+format_time( const struct tm* p, char* buf )
+{
+    sprintf( buf, "%d/%d/%2d %d:%02d:%02d", 
+            p->tm_mon, p->tm_mday, p->tm_year,
+            p->tm_hour, p->tm_min, p->tm_sec);
+    return buf;
+}
+
+// return a courser but cheaper estimate of sidereal time
+double sidereal_course(fgTIME *t, double lng) {
+    struct tm *gmt;
+    time_t start_gmt, now;
+    double diff, part, days, hours, lst;
+    char tbuf[64];
+
+    gmt = t->gmt;
+    now = t->cur_time;
+    start_gmt = get_start_gmt(gmt->tm_year);
+
+    FG_LOG( FG_EVENT, FG_DEBUG, "  COURSE: GMT = " << format_time(gmt, tbuf) );
+    FG_LOG( FG_EVENT, FG_DEBUG, "  March 21 noon (GMT) = " << start_gmt );
 
     diff = (now - start_gmt) / (3600.0 * 24.0);
     
-    fgPrintf( FG_EVENT, FG_DEBUG, 
-             "  Time since 3/21/%2d GMT = %.2f\n", gmt->tm_year, diff);
+    FG_LOG( FG_EVENT, FG_DEBUG, 
+           "  Time since 3/21/" << gmt->tm_year << " GMT = " << diff );
 
     part = fmod(diff, 1.0);
     days = diff - part;
@@ -330,33 +324,39 @@ double sidereal_course(struct tm *gmt, time_t now, double lng) {
        lst += 24.0;
     }
 
-    fgPrintf( FG_EVENT, FG_DEBUG,
-             "  days = %.1f  hours = %.2f  lon = %.2f  lst = %.2f\n", 
-             days, hours, lng, lst);
+    FG_LOG( FG_EVENT, FG_DEBUG,
+           "  days = " << days << "  hours = " << hours << "  lon = " 
+           << lng << "  lst = " << lst );
 
     return(lst);
 }
 
 
 // Update time variables such as gmt, julian date, and sidereal time
-void fgTimeUpdate(fgFLIGHT *f, fgTIME *t) {
+void fgTimeUpdate(FGInterface *f, fgTIME *t) {
     double gst_precise, gst_course;
 
-    fgPrintf( FG_EVENT, FG_BULK, "Updating time\n");
+    FG_LOG( FG_EVENT, FG_DEBUG, "Updating time" );
 
     // get current Unix calendar time (in seconds)
     t->warp += t->warp_delta;
     t->cur_time = time(NULL) + t->warp;
-    fgPrintf( FG_EVENT, FG_BULK, 
-             "  Current Unix calendar time = %ld  warp = %ld  delta = %ld\n", 
-             t->cur_time, t->warp, t->warp_delta);
+    FG_LOG( FG_EVENT, FG_DEBUG, 
+           "  Current Unix calendar time = " << t->cur_time 
+           << "  warp = " << t->warp << "  delta = " << t->warp_delta );
+
+    if ( t->warp_delta ) {
+       // time is changing so force an update
+       local_update_sky_and_lighting_params();
+    }
 
     // get GMT break down for current time
     t->gmt = gmtime(&t->cur_time);
-    fgPrintf( FG_EVENT, FG_BULK, 
-             "  Current GMT = %d/%d/%2d %d:%02d:%02d\n", 
-             t->gmt->tm_mon+1, t->gmt->tm_mday, t->gmt->tm_year,
-             t->gmt->tm_hour, t->gmt->tm_min, t->gmt->tm_sec);
+    FG_LOG( FG_EVENT, FG_DEBUG, 
+           "  Current GMT = " << t->gmt->tm_mon+1 << "/" 
+           << t->gmt->tm_mday << "/" << t->gmt->tm_year << " "
+           << t->gmt->tm_hour << ":" << t->gmt->tm_min << ":" 
+           << t->gmt->tm_sec );
 
     // calculate modified Julian date
     t->mjd = cal_mjd ((int)(t->gmt->tm_mon+1), (double)t->gmt->tm_mday, 
@@ -368,7 +368,7 @@ void fgTimeUpdate(fgFLIGHT *f, fgTIME *t) {
 
     // convert "back" to Julian date + partial day (as a fraction of one)
     t->jd = t->mjd + MJD0;
-    fgPrintf( FG_EVENT, FG_BULK, "  Current Julian Date = %.5f\n", t->jd);
+    FG_LOG( FG_EVENT, FG_DEBUG, "  Current Julian Date = " << t->jd );
 
     // printf("  Current Longitude = %.3f\n", FG_Longitude * RAD_TO_DEG);
 
@@ -376,32 +376,140 @@ void fgTimeUpdate(fgFLIGHT *f, fgTIME *t) {
     if ( t->gst_diff < -100.0 ) {
        // first time through do the expensive calculation & cheap
         // calculation to get the difference.
-      fgPrintf( FG_EVENT, FG_INFO, "  First time, doing precise gst\n");
+      FG_LOG( FG_EVENT, FG_INFO, "  First time, doing precise gst" );
       t->gst = gst_precise = sidereal_precise(t->mjd, 0.00);
-      gst_course = sidereal_course(t->gmt, t->cur_time, 0.00);
+      gst_course = sidereal_course(t, 0.00);
       t->gst_diff = gst_precise - gst_course;
 
-      t->lst = 
-       sidereal_course(t->gmt, t->cur_time, -(FG_Longitude * RAD_TO_DEG))
-       + t->gst_diff;
+      t->lst =
+         sidereal_course(t, -(f->get_Longitude() * RAD_TO_DEG)) + t->gst_diff;
     } else {
        // course + difference should drift off very slowly
-       t->gst = 
-           sidereal_course(t->gmt, t->cur_time, 0.00) + t->gst_diff;
-       t->lst = 
-           sidereal_course(t->gmt, t->cur_time, -(FG_Longitude * RAD_TO_DEG))
-           + t->gst_diff;
+       t->gst = sidereal_course(t, 0.00) + t->gst_diff;
+       t->lst = sidereal_course(t, -(f->get_Longitude() * RAD_TO_DEG)) + 
+           t->gst_diff;
     }
-    fgPrintf( FG_EVENT, FG_DEBUG,
-             "  Current lon=0.00 Sidereal Time = %.3f\n", t->gst);
-    fgPrintf( FG_EVENT, FG_DEBUG,
-             "  Current LOCAL Sidereal Time = %.3f (%.3f) (diff = %.3f)\n", 
-             t->lst, sidereal_precise(t->mjd, -(FG_Longitude * RAD_TO_DEG)),
-             t->gst_diff);
+    FG_LOG( FG_EVENT, FG_DEBUG,
+           "  Current lon=0.00 Sidereal Time = " << t->gst );
+    FG_LOG( FG_EVENT, FG_DEBUG,
+           "  Current LOCAL Sidereal Time = " << t->lst << " (" 
+           << sidereal_precise(t->mjd, -(f->get_Longitude() * RAD_TO_DEG)) 
+           << ") (diff = " << t->gst_diff << ")" );
 }
 
 
 // $Log$
+// Revision 1.31  1999/02/05 21:29:18  curt
+// Modifications to incorporate Jon S. Berndts flight model code.
+//
+// Revision 1.30  1999/02/01 21:33:37  curt
+// Renamed FlightGear/Simulator/Flight to FlightGear/Simulator/FDM since
+// Jon accepted my offer to do this and thought it was a good idea.
+//
+// Revision 1.29  1999/01/19 20:57:08  curt
+// MacOS portability changes contributed by "Robert Puyol" <puyol@abvent.fr>
+//
+// Revision 1.28  1999/01/07 20:25:34  curt
+// Portability changes and updates from Bernie Bright.
+//
+// Revision 1.27  1998/12/11 20:26:55  curt
+// #include tweaks.
+//
+// Revision 1.26  1998/12/05 15:54:28  curt
+// Renamed class fgFLIGHT to class FGState as per request by JSB.
+//
+// Revision 1.25  1998/12/05 14:21:30  curt
+// Moved struct fg_timestamp to class fgTIMESTAMP and moved it's definition
+// to it's own file, timestamp.hxx.
+//
+// Revision 1.24  1998/12/04 01:32:49  curt
+// Converted "struct fg_timestamp" to "class fgTIMESTAMP" and added some
+// convenience inline operators.
+//
+// Revision 1.23  1998/12/03 01:18:40  curt
+// Converted fgFLIGHT to a class.
+//
+// Revision 1.22  1998/11/16 14:00:28  curt
+// FG_LOG() message tweaks.
+//
+// Revision 1.21  1998/11/06 21:18:26  curt
+// Converted to new logstream debugging facility.  This allows release
+// builds with no messages at all (and no performance impact) by using
+// the -DFG_NDEBUG flag.
+//
+// Revision 1.20  1998/11/02 18:25:38  curt
+// Check for __CYGWIN__ (b20) as well as __CYGWIN32__ (pre b20 compilers)
+// Other misc. tweaks.
+//
+// Revision 1.19  1998/10/17 01:34:29  curt
+// C++ ifying ...
+//
+// Revision 1.18  1998/10/02 21:36:09  curt
+// Fixes to try to break through the win95/98 18.3 fps barrier.
+//
+// Revision 1.17  1998/09/15 04:27:49  curt
+// Changes for new astro code.
+//
+// Revision 1.16  1998/08/29 13:11:32  curt
+// Bernie Bright writes:
+//   I've created some new classes to enable pointers-to-functions and
+//   pointers-to-class-methods to be treated like objects.  These objects
+//   can be registered with fgEVENT_MGR.
+//
+//   File "Include/fg_callback.hxx" contains the callback class defns.
+//
+//   Modified fgEVENT and fgEVENT_MGR to use the callback classes.  Also
+//   some minor tweaks to STL usage.
+//
+//   Added file "Include/fg_stl_config.h" to deal with STL portability
+//   issues.  I've added an initial config for egcs (and probably gcc-2.8.x).
+//   I don't have access to Visual C++ so I've left that for someone else.
+//   This file is influenced by the stl_config.h file delivered with egcs.
+//
+//   Added "Include/auto_ptr.hxx" which contains an implementation of the
+//   STL auto_ptr class which is not provided in all STL implementations
+//   and is needed to use the callback classes.
+//
+//   Deleted fgLightUpdate() which was just a wrapper to call
+//   fgLIGHT::Update().
+//
+//   Modified fg_init.cxx to register two method callbacks in place of the
+//   old wrapper functions.
+//
+// Revision 1.15  1998/08/24 20:12:16  curt
+// Rewrote sidereal_course with simpler parameters.
+//
+// Revision 1.14  1998/08/05 00:20:07  curt
+// Added a local routine to update lighting params every frame when time is
+// accelerated.
+//
+// Revision 1.13  1998/07/30 23:48:55  curt
+// Sgi build tweaks.
+// Pause support.
+//
+// Revision 1.12  1998/07/27 18:42:22  curt
+// Added a pause option.
+//
+// Revision 1.11  1998/07/22 21:45:37  curt
+// fg_time.cxx: Removed call to ctime() in a printf() which should be harmless
+//   but seems to be triggering a bug.
+// light.cxx: Added code to adjust fog color based on sunrise/sunset effects
+//   and view orientation.  This is an attempt to match the fog color to the
+//   sky color in the center of the screen.  You see discrepancies at the
+//   edges, but what else can be done?
+// sunpos.cxx: Caculate local direction to sun here.  (what compass direction
+//   do we need to face to point directly at sun)
+//
+// Revision 1.10  1998/07/13 21:02:07  curt
+// Wrote access functions for current fgOPTIONS.
+//
+// Revision 1.9  1998/06/12 00:59:53  curt
+// Build only static libraries.
+// Declare memmove/memset for Sloaris.
+// Rewrote fg_time.c routine to get LST start seconds to better handle
+//   Solaris, and be easier to port, and understand the GMT vs. local
+//   timezone issues.
+//
 // Revision 1.8  1998/06/05 18:18:13  curt
 // Incorporated some automake conditionals to try to support mktime() correctly
 // on a wider variety of platforms.