Create TimeOfDayInterpolator class to refactor time handling in WeatherManager

openmw-37
scrawl 9 years ago
parent 8da4530957
commit 45bf3e6788

@ -31,17 +31,74 @@ namespace
{
static const int invalidWeatherID = -1;
// linear interpolate between x and y based on factor.
float lerp (float x, float y, float factor)
{
return x * (1-factor) + y * factor;
}
// linear interpolate between x and y based on factor.
osg::Vec4f lerp (const osg::Vec4f& x, const osg::Vec4f& y, float factor)
{
return x * (1-factor) + y * factor;
}
}
template <typename T>
T TimeOfDayInterpolator<T>::getValue(const float gameHour, const TimeOfDaySettings& timeSettings) const
{
// TODO: use pre/post sunset/sunrise time values in [Weather] section
// night
if (gameHour <= timeSettings.mNightEnd || gameHour >= timeSettings.mNightStart + 1)
return mNightValue;
// sunrise
else if (gameHour >= timeSettings.mNightEnd && gameHour <= timeSettings.mDayStart + 1)
{
if (gameHour <= timeSettings.mSunriseTime)
{
// fade in
float advance = timeSettings.mSunriseTime - gameHour;
float factor = advance / 0.5f;
return lerp(mSunriseValue, mNightValue, factor);
}
else
{
// fade out
float advance = gameHour - timeSettings.mSunriseTime;
float factor = advance / 3.f;
return lerp(mSunriseValue, mDayValue, factor);
}
}
// day
else if (gameHour >= timeSettings.mDayStart + 1 && gameHour <= timeSettings.mDayEnd - 1)
return mDayValue;
// sunset
else if (gameHour >= timeSettings.mDayEnd - 1 && gameHour <= timeSettings.mNightStart + 1)
{
if (gameHour <= timeSettings.mDayEnd + 1)
{
// fade in
float advance = (timeSettings.mDayEnd + 1) - gameHour;
float factor = (advance / 2);
return lerp(mSunsetValue, mDayValue, factor);
}
else
{
// fade out
float advance = gameHour - (timeSettings.mDayEnd + 1);
float factor = advance / 2.f;
return lerp(mSunsetValue, mNightValue, factor);
}
}
// shut up compiler
return T();
}
template class TimeOfDayInterpolator<float>;
template class TimeOfDayInterpolator<osg::Vec4f>;
Weather::Weather(const std::string& name,
const MWWorld::Fallback& fallback,
float stormWindSpeed,
@ -49,22 +106,22 @@ Weather::Weather(const std::string& name,
const std::string& ambientLoopSoundID,
const std::string& particleEffect)
: mCloudTexture(fallback.getFallbackString("Weather_" + name + "_Cloud_Texture"))
, mSkySunriseColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"))
, mSkyDayColor(fallback.getFallbackColour("Weather_" + name + "_Sky_Day_Color"))
, mSkySunsetColor(fallback.getFallbackColour("Weather_" + name + "_Sky_Sunset_Color"))
, mSkyNightColor(fallback.getFallbackColour("Weather_" + name + "_Sky_Night_Color"))
, mFogSunriseColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Sunrise_Color"))
, mFogDayColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Day_Color"))
, mFogSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Sunset_Color"))
, mFogNightColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Night_Color"))
, mAmbientSunriseColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunrise_Color"))
, mAmbientDayColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Day_Color"))
, mAmbientSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunset_Color"))
, mAmbientNightColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Night_Color"))
, mSunSunriseColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Sunrise_Color"))
, mSunDayColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Day_Color"))
, mSunSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Sunset_Color"))
, mSunNightColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Night_Color"))
, mSkyColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sky_Day_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sky_Sunset_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sky_Night_Color"))
, mFogColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Sunrise_Color"),
fallback.getFallbackColour("Weather_" + name + "_Fog_Day_Color"),
fallback.getFallbackColour("Weather_" + name + "_Fog_Sunset_Color"),
fallback.getFallbackColour("Weather_" + name + "_Fog_Night_Color"))
, mAmbientColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunrise_Color"),
fallback.getFallbackColour("Weather_" + name + "_Ambient_Day_Color"),
fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunset_Color"),
fallback.getFallbackColour("Weather_" + name + "_Ambient_Night_Color"))
, mSunColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Sunrise_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sun_Day_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sun_Sunset_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sun_Night_Color"))
, mLandFogDayDepth(fallback.getFallbackFloat("Weather_" + name + "_Land_Fog_Day_Depth"))
, mLandFogNightDepth(fallback.getFallbackFloat("Weather_" + name + "_Land_Fog_Night_Depth"))
, mSunDiscSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Disc_Sunset_Color"))
@ -432,16 +489,13 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const MWWo
, mSunriseDuration(fallback.getFallbackFloat("Weather_Sunrise_Duration"))
, mSunsetDuration(fallback.getFallbackFloat("Weather_Sunset_Duration"))
, mSunPreSunsetTime(fallback.getFallbackFloat("Weather_Sun_Pre-Sunset_Time"))
, mNightStart(mSunsetTime + mSunsetDuration)
, mNightEnd(mSunriseTime - 0.5f)
, mDayStart(mSunriseTime + mSunriseDuration)
, mDayEnd(mSunsetTime)
, mNightFade(0, 0, 0, 1)
, mHoursBetweenWeatherChanges(fallback.getFallbackFloat("Weather_Hours_Between_Weather_Changes"))
, mRainSpeed(fallback.getFallbackFloat("Weather_Precip_Gravity"))
, mUnderwaterSunriseFog(fallback.getFallbackFloat("Water_UnderwaterSunriseFog"))
, mUnderwaterDayFog(fallback.getFallbackFloat("Water_UnderwaterDayFog"))
, mUnderwaterSunsetFog(fallback.getFallbackFloat("Water_UnderwaterSunsetFog"))
, mUnderwaterNightFog(fallback.getFallbackFloat("Water_UnderwaterNightFog"))
, mUnderwaterFog(fallback.getFallbackFloat("Water_UnderwaterSunriseFog"),
fallback.getFallbackFloat("Water_UnderwaterDayFog"),
fallback.getFallbackFloat("Water_UnderwaterSunsetFog"),
fallback.getFallbackFloat("Water_UnderwaterNightFog"))
, mWeatherSettings()
, mMasser("Masser", fallback)
, mSecunda("Secunda", fallback)
@ -461,6 +515,12 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const MWWo
, mAmbientSound()
, mPlayingSoundID()
{
mTimeSettings.mNightStart = mSunsetTime + mSunsetDuration;
mTimeSettings.mNightEnd = mSunriseTime - 0.5f;
mTimeSettings.mDayStart = mSunriseTime + mSunriseDuration;
mTimeSettings.mDayEnd = mSunsetTime;
mTimeSettings.mSunriseTime = mSunriseTime;
mWeatherSettings.reserve(10);
addWeather("Clear", fallback); // 0
addWeather("Cloudy", fallback); // 1
@ -593,7 +653,7 @@ void WeatherManager::update(float duration, bool paused)
}
// disable sun during night
if (time.getHour() >= mNightStart || time.getHour() <= mSunriseTime)
if (time.getHour() >= mTimeSettings.mNightStart || time.getHour() <= mSunriseTime)
mRendering.getSkyManager()->sunDisable();
else
mRendering.getSkyManager()->sunEnable();
@ -604,10 +664,10 @@ void WeatherManager::update(float duration, bool paused)
{
// Shift times into a 24-hour window beginning at mSunriseTime...
float adjustedHour = time.getHour();
float adjustedNightStart = mNightStart;
float adjustedNightStart = mTimeSettings.mNightStart;
if ( time.getHour() < mSunriseTime )
adjustedHour += 24.f;
if ( mNightStart < mSunriseTime )
if ( mTimeSettings.mNightStart < mSunriseTime )
adjustedNightStart += 24.f;
const bool is_night = adjustedHour >= adjustedNightStart;
@ -628,52 +688,7 @@ void WeatherManager::update(float duration, bool paused)
mRendering.setSunDirection( final * -1 );
}
// TODO: use pre/post sunset/sunrise time values in [Weather] section
// TODO: factor out the time of day interpolation code to reuse for calculateWeatherResult()
float gameHour = time.getHour();
float underwaterFog;
// night
if (gameHour <= mNightEnd || gameHour >= mNightStart + 1)
underwaterFog = mUnderwaterNightFog;
// sunrise
else if (gameHour >= mNightEnd && gameHour <= mDayStart + 1)
{
if (gameHour <= mSunriseTime)
{
// fade in
float advance = mSunriseTime - gameHour;
float factor = advance / 0.5f;
underwaterFog = lerp(mUnderwaterSunriseFog, mUnderwaterNightFog, factor);
}
else //if (gameHour >= 6)
{
// fade out
float advance = gameHour - mSunriseTime;
float factor = advance / 3.f;
underwaterFog = lerp(mUnderwaterSunriseFog, mUnderwaterDayFog, factor);
}
}
// day
else if (gameHour >= mDayStart + 1 && gameHour <= mDayEnd - 1)
underwaterFog = mUnderwaterDayFog;
// sunset
else if (gameHour >= mDayEnd - 1 && gameHour <= mNightStart + 1)
{
if (gameHour <= mDayEnd + 1)
{
// fade in
float advance = (mDayEnd + 1) - gameHour;
float factor = (advance / 2);
underwaterFog = lerp(mUnderwaterSunsetFog, mUnderwaterDayFog, factor);
}
else //if (gameHour >= 19)
{
// fade out
float advance = gameHour - (mDayEnd + 1);
float factor = advance / 2.f;
underwaterFog = lerp(mUnderwaterSunsetFog, mUnderwaterNightFog, factor);
}
}
float underwaterFog = mUnderwaterFog.getValue(time.getHour(), mTimeSettings);
float peakHour = mSunriseTime + (mSunsetTime - mSunriseTime) / 2;
if (time.getHour() < mSunriseTime || time.getHour() > mSunsetTime)
@ -748,7 +763,7 @@ bool WeatherManager::isDark() const
TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp();
bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior()
|| MWBase::Environment::get().getWorld()->isCellQuasiExterior());
return exterior && (time.getHour() < mSunriseTime || time.getHour() > mNightStart - 1);
return exterior && (time.getHour() < mSunriseTime || time.getHour() > mTimeSettings.mNightStart - 1);
}
void WeatherManager::write(ESM::ESMWriter& writer, Loading::Listener& progress)
@ -1026,81 +1041,15 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam
mResult.mParticleEffect = current.mParticleEffect;
mResult.mRainEffect = current.mRainEffect;
mResult.mNight = (gameHour < mSunriseTime || gameHour > mNightStart - 1);
mResult.mNight = (gameHour < mSunriseTime || gameHour > mTimeSettings.mNightStart - 1);
mResult.mFogDepth = mResult.mNight ? current.mLandFogNightDepth : current.mLandFogDayDepth;
// TODO: use pre/post sunset/sunrise time values in [Weather] section
// night
if (gameHour <= mNightEnd || gameHour >= mNightStart + 1)
{
mResult.mFogColor = current.mFogNightColor;
mResult.mAmbientColor = current.mAmbientNightColor;
mResult.mSunColor = current.mSunNightColor;
mResult.mSkyColor = current.mSkyNightColor;
mResult.mNightFade = 1.f;
}
// sunrise
else if (gameHour >= mNightEnd && gameHour <= mDayStart + 1)
{
if (gameHour <= mSunriseTime)
{
// fade in
float advance = mSunriseTime - gameHour;
float factor = advance / 0.5f;
mResult.mFogColor = lerp(current.mFogSunriseColor, current.mFogNightColor, factor);
mResult.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientNightColor, factor);
mResult.mSunColor = lerp(current.mSunSunriseColor, current.mSunNightColor, factor);
mResult.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyNightColor, factor);
mResult.mNightFade = factor;
}
else //if (gameHour >= 6)
{
// fade out
float advance = gameHour - mSunriseTime;
float factor = advance / 3.f;
mResult.mFogColor = lerp(current.mFogSunriseColor, current.mFogDayColor, factor);
mResult.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientDayColor, factor);
mResult.mSunColor = lerp(current.mSunSunriseColor, current.mSunDayColor, factor);
mResult.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyDayColor, factor);
}
}
// day
else if (gameHour >= mDayStart + 1 && gameHour <= mDayEnd - 1)
{
mResult.mFogColor = current.mFogDayColor;
mResult.mAmbientColor = current.mAmbientDayColor;
mResult.mSunColor = current.mSunDayColor;
mResult.mSkyColor = current.mSkyDayColor;
}
// sunset
else if (gameHour >= mDayEnd - 1 && gameHour <= mNightStart + 1)
{
if (gameHour <= mDayEnd + 1)
{
// fade in
float advance = (mDayEnd + 1) - gameHour;
float factor = (advance / 2);
mResult.mFogColor = lerp(current.mFogSunsetColor, current.mFogDayColor, factor);
mResult.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientDayColor, factor);
mResult.mSunColor = lerp(current.mSunSunsetColor, current.mSunDayColor, factor);
mResult.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyDayColor, factor);
}
else //if (gameHour >= 19)
{
// fade out
float advance = gameHour - (mDayEnd + 1);
float factor = advance / 2.f;
mResult.mFogColor = lerp(current.mFogSunsetColor, current.mFogNightColor, factor);
mResult.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientNightColor, factor);
mResult.mSunColor = lerp(current.mSunSunsetColor, current.mSunNightColor, factor);
mResult.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyNightColor, factor);
mResult.mNightFade = factor;
}
}
mResult.mFogColor = current.mFogColor.getValue(gameHour, mTimeSettings);
mResult.mAmbientColor = current.mAmbientColor.getValue(gameHour, mTimeSettings);
mResult.mSunColor = current.mSunColor.getValue(gameHour, mTimeSettings);
mResult.mSkyColor = current.mSkyColor.getValue(gameHour, mTimeSettings);
mResult.mNightFade = mNightFade.getValue(gameHour, mTimeSettings);
if (gameHour >= mSunsetTime - mSunPreSunsetTime)
{

@ -34,6 +34,33 @@ namespace MWWorld
class Fallback;
class TimeStamp;
struct TimeOfDaySettings
{
float mNightStart;
float mNightEnd;
float mDayStart;
float mDayEnd;
float mSunriseTime;
};
/// Interpolates between 4 data points (sunrise, day, sunset, night) based on the time of day.
/// The template value could be a floating point number, or a color.
template <typename T>
class TimeOfDayInterpolator
{
public:
TimeOfDayInterpolator(const T& sunrise, const T& day, const T& sunset, const T& night)
: mSunriseValue(sunrise), mDayValue(day), mSunsetValue(sunset), mNightValue(night)
{
}
T getValue (const float gameHour, const TimeOfDaySettings& timeSettings) const;
private:
T mSunriseValue, mDayValue, mSunsetValue, mNightValue;
};
/// Defines a single weather setting (according to INI)
class Weather
{
@ -47,29 +74,14 @@ namespace MWWorld
std::string mCloudTexture;
// Sky (atmosphere) colors
osg::Vec4f mSkySunriseColor;
osg::Vec4f mSkyDayColor;
osg::Vec4f mSkySunsetColor;
osg::Vec4f mSkyNightColor;
// Fog colors
osg::Vec4f mFogSunriseColor;
osg::Vec4f mFogDayColor;
osg::Vec4f mFogSunsetColor;
osg::Vec4f mFogNightColor;
// Ambient lighting colors
osg::Vec4f mAmbientSunriseColor;
osg::Vec4f mAmbientDayColor;
osg::Vec4f mAmbientSunsetColor;
osg::Vec4f mAmbientNightColor;
// Sun (directional) lighting colors
osg::Vec4f mSunSunriseColor;
osg::Vec4f mSunDayColor;
osg::Vec4f mSunSunsetColor;
osg::Vec4f mSunNightColor;
// Sky (atmosphere) color
TimeOfDayInterpolator<osg::Vec4f> mSkyColor;
// Fog color
TimeOfDayInterpolator<osg::Vec4f> mFogColor;
// Ambient lighting color
TimeOfDayInterpolator<osg::Vec4f> mAmbientColor;
// Sun (directional) lighting color
TimeOfDayInterpolator<osg::Vec4f> mSunColor;
// Fog depth/density
float mLandFogDayDepth;
@ -243,18 +255,17 @@ namespace MWWorld
float mSunriseDuration;
float mSunsetDuration;
float mSunPreSunsetTime;
float mNightStart;
float mNightEnd;
float mDayStart;
float mDayEnd;
TimeOfDaySettings mTimeSettings;
// fading of night skydome
TimeOfDayInterpolator<float> mNightFade;
float mHoursBetweenWeatherChanges;
float mRainSpeed;
// underwater fog not really related to weather, but we handle it here because it's convenient
float mUnderwaterSunriseFog;
float mUnderwaterDayFog;
float mUnderwaterSunsetFog;
float mUnderwaterNightFog;
TimeOfDayInterpolator<float> mUnderwaterFog;
std::vector<Weather> mWeatherSettings;
MoonModel mMasser;

Loading…
Cancel
Save