Create TimeManager subsystem, and collect the time related code out of main.cxx and fg_init.cxx into it.
Remove the unfortunately named 'tmp.[cxx|hxx]', pushing the remaining code in FGLight.
This commit is contained in:
parent
7aba4333a2
commit
50eb95dcad
17 changed files with 616 additions and 697 deletions
|
@ -4512,11 +4512,11 @@
|
|||
>
|
||||
</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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
@ -107,8 +105,6 @@
|
|||
#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"));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() );
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
359
src/Time/TimeManager.cxx
Normal file
359
src/Time/TimeManager.cxx
Normal file
|
@ -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() );
|
||||
}
|
78
src/Time/TimeManager.hxx
Normal file
78
src/Time/TimeManager.hxx
Normal file
|
@ -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
|
|
@ -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>
|
||||
|
@ -44,7 +46,38 @@
|
|||
#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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
#include "tmp.hxx"
|
||||
#include "sunsolver.hxx"
|
||||
|
||||
|
||||
|
|
238
src/Time/tmp.cxx
238
src/Time/tmp.cxx
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
Loading…
Reference in a new issue