Corrected some weather transition calculations

Reversed some formulas for Transition Delta and Clouds Maximum Percent
and implemented them. Refactored Weather some to encapsulate those
formulas (to more closely match MoonModel). Did some small cleanup of
WeatherManager.
sceneinput
slothlife 10 years ago
parent af5ffa5548
commit 3d419a612a

@ -37,6 +37,68 @@ namespace
} }
} }
Weather::Weather(const std::string& name,
const MWWorld::Fallback& fallback,
float stormWindSpeed,
float rainSpeed,
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"))
, 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"))
, mWindSpeed(fallback.getFallbackFloat("Weather_" + name + "_Wind_Speed"))
, mCloudSpeed(fallback.getFallbackFloat("Weather_" + name + "_Cloud_Speed"))
, mGlareView(fallback.getFallbackFloat("Weather_" + name + "_Glare_View"))
, mAmbientLoopSoundID(ambientLoopSoundID)
, mIsStorm(mWindSpeed > stormWindSpeed)
, mRainSpeed(rainSpeed)
, mRainFrequency(fallback.getFallbackFloat("Weather_" + name + "_Rain_Entrance_Speed"))
, mParticleEffect(particleEffect)
, mRainEffect(fallback.getFallbackBool("Weather_" + name + "_Using_Precip") ? "meshes\\raindrop.nif" : "")
, mTransitionDelta(fallback.getFallbackFloat("Weather_" + name + "_Transition_Delta"))
, mCloudsMaximumPercent(fallback.getFallbackFloat("Weather_" + name + "_Clouds_Maximum_Percent"))
{
/*
Unhandled:
Rain Diameter=600 ?
Rain Height Min=200 ?
Rain Height Max=700 ?
Rain Threshold=0.6 ?
Max Raindrops=650 ?
*/
}
float Weather::transitionSeconds() const
{
// This formula is reversed from Morrowind by observing different Transition Delta values with Clouds
// Maximum Percent set to 1.0, and watching for when the light from the sun was no longer visible.
static const float deltasPerHour = 0.00835;
return (deltasPerHour / mTransitionDelta) * 60.0f * 60.0f;
}
float Weather::cloudBlendFactor(float transitionRatio) const
{
// Clouds Maximum Percent affects how quickly the sky transitions from one sky texture to the next.
return transitionRatio / mCloudsMaximumPercent;
}
MoonModel::MoonModel(const std::string& name, const MWWorld::Fallback& fallback) MoonModel::MoonModel(const std::string& name, const MWWorld::Fallback& fallback)
: mFadeInStart(fallback.getFallbackFloat("Moons_" + name + "_Fade_In_Start")) : mFadeInStart(fallback.getFallbackFloat("Moons_" + name + "_Fade_In_Start"))
, mFadeInFinish(fallback.getFallbackFloat("Moons_" + name + "_Fade_In_Finish")) , mFadeInFinish(fallback.getFallbackFloat("Moons_" + name + "_Fade_In_Finish"))
@ -206,80 +268,29 @@ inline float MoonModel::earlyMoonShadowAlpha(float angle) const
return 0.0f; return 0.0f;
} }
void WeatherManager::setFallbackWeather(Weather& weather,const std::string& name)
{
std::string upper=name;
upper[0]=toupper(name[0]);
weather.mCloudsMaximumPercent = mFallback->getFallbackFloat("Weather_"+upper+"_Clouds_Maximum_Percent");
weather.mTransitionDelta = mFallback->getFallbackFloat("Weather_"+upper+"_Transition_Delta");
weather.mSkySunriseColor=mFallback->getFallbackColour("Weather_"+upper+"_Sky_Sunrise_Color");
weather.mSkyDayColor = mFallback->getFallbackColour("Weather_"+upper+"_Sky_Day_Color");
weather.mSkySunsetColor = mFallback->getFallbackColour("Weather_"+upper+"_Sky_Sunset_Color");
weather.mSkyNightColor = mFallback->getFallbackColour("Weather_"+upper+"_Sky_Night_Color");
weather.mFogSunriseColor = mFallback->getFallbackColour("Weather_"+upper+"_Fog_Sunrise_Color");
weather.mFogDayColor = mFallback->getFallbackColour("Weather_"+upper+"_Fog_Day_Color");
weather.mFogSunsetColor = mFallback->getFallbackColour("Weather_"+upper+"_Fog_Sunset_Color");
weather.mFogNightColor = mFallback->getFallbackColour("Weather_"+upper+"_Fog_Night_Color");
weather.mAmbientSunriseColor = mFallback->getFallbackColour("Weather_"+upper+"_Ambient_Sunrise_Color");
weather.mAmbientDayColor = mFallback->getFallbackColour("Weather_"+upper+"_Ambient_Day_Color");
weather.mAmbientSunsetColor = mFallback->getFallbackColour("Weather_"+upper+"_Ambient_Sunset_Color");
weather.mAmbientNightColor = mFallback->getFallbackColour("Weather_"+upper+"_Ambient_Night_Color");
weather.mSunSunriseColor = mFallback->getFallbackColour("Weather_"+upper+"_Sun_Sunrise_Color");
weather.mSunDayColor = mFallback->getFallbackColour("Weather_"+upper+"_Sun_Day_Color");
weather.mSunSunsetColor = mFallback->getFallbackColour("Weather_"+upper+"_Sun_Sunset_Color");
weather.mSunNightColor = mFallback->getFallbackColour("Weather_"+upper+"_Sun_Night_Color");
weather.mSunDiscSunsetColor = mFallback->getFallbackColour("Weather_"+upper+"_Sun_Disc_Sunset_Color");
weather.mLandFogDayDepth = mFallback->getFallbackFloat("Weather_"+upper+"_Land_Fog_Day_Depth");
weather.mLandFogNightDepth = mFallback->getFallbackFloat("Weather_"+upper+"_Land_Fog_Night_Depth");
weather.mWindSpeed = mFallback->getFallbackFloat("Weather_"+upper+"_Wind_Speed");
weather.mCloudSpeed = mFallback->getFallbackFloat("Weather_"+upper+"_Cloud_Speed");
weather.mGlareView = mFallback->getFallbackFloat("Weather_"+upper+"_Glare_View");
weather.mCloudTexture = mFallback->getFallbackString("Weather_"+upper+"_Cloud_Texture");
static const float fStromWindSpeed = mStore->get<ESM::GameSetting>().find("fStromWindSpeed")->getFloat();
weather.mIsStorm = weather.mWindSpeed > fStromWindSpeed;
bool usesPrecip = mFallback->getFallbackBool("Weather_"+upper+"_Using_Precip");
if (usesPrecip)
weather.mRainEffect = "meshes\\raindrop.nif";
weather.mRainSpeed = mRainSpeed;
weather.mRainFrequency = mFallback->getFallbackFloat("Weather_"+upper+"_Rain_Entrance_Speed");
/*
Unhandled:
Rain Diameter=600 ?
Rain Height Min=200 ?
Rain Height Max=700 ?
Rain Threshold=0.6 ?
Max Raindrops=650 ?
*/
mWeatherSettings[name] = weather;
}
WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::Fallback* fallback, MWWorld::ESMStore* store) : WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::Fallback* fallback, MWWorld::ESMStore* store) :
mHour(14), mWindSpeed(0.f), mIsStorm(false), mStormDirection(0,1,0), mFallback(fallback), mStore(store), mHour(14), mWindSpeed(0.f), mIsStorm(false), mStormDirection(0,1,0), mStore(store),
mRendering(rendering), mCurrentWeather("clear"), mNextWeather(""), mFirstUpdate(true), mRendering(rendering), mCurrentWeather("clear"), mNextWeather(""), mFirstUpdate(true),
mRemainingTransitionTime(0), mThunderFlash(0), mThunderChance(0), mThunderChanceNeeded(50), mRemainingTransitionTime(0), mThunderFlash(0), mThunderChance(0), mThunderChanceNeeded(50),
mTimePassed(0), mWeatherUpdateTime(0), mThunderSoundDelay(0), mTimePassed(0), mWeatherUpdateTime(0), mThunderSoundDelay(0),
mMasser("Masser", *fallback), mSecunda("Secunda", *fallback) mMasser("Masser", *fallback), mSecunda("Secunda", *fallback)
{ {
//Globals //Globals
mThunderSoundID0 = mFallback->getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_0"); mThunderSoundID0 = fallback->getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_0");
mThunderSoundID1 = mFallback->getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_1"); mThunderSoundID1 = fallback->getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_1");
mThunderSoundID2 = mFallback->getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_2"); mThunderSoundID2 = fallback->getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_2");
mThunderSoundID3 = mFallback->getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_3"); mThunderSoundID3 = fallback->getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_3");
mSunriseTime = mFallback->getFallbackFloat("Weather_Sunrise_Time"); mSunriseTime = fallback->getFallbackFloat("Weather_Sunrise_Time");
mSunsetTime = mFallback->getFallbackFloat("Weather_Sunset_Time"); mSunsetTime = fallback->getFallbackFloat("Weather_Sunset_Time");
mSunriseDuration = mFallback->getFallbackFloat("Weather_Sunrise_Duration"); mSunriseDuration = fallback->getFallbackFloat("Weather_Sunrise_Duration");
mSunsetDuration = mFallback->getFallbackFloat("Weather_Sunset_Duration"); mSunsetDuration = fallback->getFallbackFloat("Weather_Sunset_Duration");
mHoursBetweenWeatherChanges = mFallback->getFallbackFloat("Weather_Hours_Between_Weather_Changes"); mHoursBetweenWeatherChanges = fallback->getFallbackFloat("Weather_Hours_Between_Weather_Changes");
mWeatherUpdateTime = mHoursBetweenWeatherChanges * 3600; mWeatherUpdateTime = mHoursBetweenWeatherChanges * 3600;
mThunderFrequency = mFallback->getFallbackFloat("Weather_Thunderstorm_Thunder_Frequency"); mThunderFrequency = fallback->getFallbackFloat("Weather_Thunderstorm_Thunder_Frequency");
mThunderThreshold = mFallback->getFallbackFloat("Weather_Thunderstorm_Thunder_Threshold"); mThunderThreshold = fallback->getFallbackFloat("Weather_Thunderstorm_Thunder_Threshold");
mThunderSoundDelay = 0.25; mThunderSoundDelay = 0.25;
mRainSpeed = mFallback->getFallbackFloat("Weather_Precip_Gravity"); mRainSpeed = fallback->getFallbackFloat("Weather_Precip_Gravity");
//Some useful values //Some useful values
/* TODO: Use pre-sunrise_time, pre-sunset_time, /* TODO: Use pre-sunrise_time, pre-sunset_time,
@ -292,47 +303,16 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::F
mDayStart = mSunriseTime + mSunriseDuration; mDayStart = mSunriseTime + mSunriseDuration;
mDayEnd = mSunsetTime; mDayEnd = mSunsetTime;
//Weather addWeather("Clear", *fallback);
Weather clear; addWeather("Cloudy", *fallback);
setFallbackWeather(clear,"clear"); addWeather("Foggy", *fallback);
addWeather("Overcast", *fallback);
Weather cloudy; addWeather("Rain", *fallback, "rain");
setFallbackWeather(cloudy,"cloudy"); addWeather("Thunderstorm", *fallback, "rain heavy");
addWeather("Ashstorm", *fallback, "ashstorm", "meshes\\ashcloud.nif");
Weather foggy; addWeather("Blight", *fallback, "blight", "meshes\\blightcloud.nif");
setFallbackWeather(foggy,"foggy"); addWeather("Snow", *fallback, "", "meshes\\snow.nif");
addWeather("Blizzard", *fallback, "BM Blizzard", "meshes\\blizzard.nif");
Weather thunderstorm;
thunderstorm.mAmbientLoopSoundID = "rain heavy";
thunderstorm.mRainEffect = "meshes\\raindrop.nif";
setFallbackWeather(thunderstorm,"thunderstorm");
Weather rain;
rain.mAmbientLoopSoundID = "rain";
rain.mRainEffect = "meshes\\raindrop.nif";
setFallbackWeather(rain,"rain");
Weather overcast;
setFallbackWeather(overcast,"overcast");
Weather ashstorm;
ashstorm.mAmbientLoopSoundID = "ashstorm";
ashstorm.mParticleEffect = "meshes\\ashcloud.nif";
setFallbackWeather(ashstorm,"ashstorm");
Weather blight;
blight.mAmbientLoopSoundID = "blight";
blight.mParticleEffect = "meshes\\blightcloud.nif";
setFallbackWeather(blight,"blight");
Weather snow;
snow.mParticleEffect = "meshes\\snow.nif";
setFallbackWeather(snow, "snow");
Weather blizzard;
blizzard.mAmbientLoopSoundID = "BM Blizzard";
blizzard.mParticleEffect = "meshes\\blizzard.nif";
setFallbackWeather(blizzard,"blizzard");
} }
WeatherManager::~WeatherManager() WeatherManager::~WeatherManager()
@ -358,19 +338,19 @@ void WeatherManager::setWeather(const std::string& weather, bool instant)
if (mNextWeather != "") if (mNextWeather != "")
{ {
// transition more than 50% finished? // transition more than 50% finished?
if (mRemainingTransitionTime/(mWeatherSettings[mCurrentWeather].mTransitionDelta * 24.f * 3600) <= 0.5) if (mRemainingTransitionTime / (findWeather(mCurrentWeather).transitionSeconds()) <= 0.5)
mCurrentWeather = mNextWeather; mCurrentWeather = mNextWeather;
} }
mNextWeather = weather; mNextWeather = weather;
mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta * 24.f * 3600.f; mRemainingTransitionTime = findWeather(mCurrentWeather).transitionSeconds();
} }
mFirstUpdate = false; mFirstUpdate = false;
} }
void WeatherManager::setResult(const std::string& weatherType) void WeatherManager::setResult(const std::string& weatherType)
{ {
const Weather& current = mWeatherSettings[weatherType]; const Weather& current = findWeather(weatherType);
mResult.mCloudTexture = current.mCloudTexture; mResult.mCloudTexture = current.mCloudTexture;
mResult.mCloudBlendFactor = 0; mResult.mCloudBlendFactor = 0;
@ -473,9 +453,11 @@ void WeatherManager::transition(float factor)
setResult(mNextWeather); setResult(mNextWeather);
const MWRender::WeatherResult other = mResult; const MWRender::WeatherResult other = mResult;
const Weather& nextWeather = findWeather(mNextWeather);
mResult.mCloudTexture = current.mCloudTexture; mResult.mCloudTexture = current.mCloudTexture;
mResult.mNextCloudTexture = other.mCloudTexture; mResult.mNextCloudTexture = other.mCloudTexture;
mResult.mCloudBlendFactor = factor; mResult.mCloudBlendFactor = nextWeather.cloudBlendFactor(factor);
mResult.mFogColor = lerp(current.mFogColor, other.mFogColor, factor); mResult.mFogColor = lerp(current.mFogColor, other.mFogColor, factor);
mResult.mSunColor = lerp(current.mSunColor, other.mSunColor, factor); mResult.mSunColor = lerp(current.mSunColor, other.mSunColor, factor);
@ -547,7 +529,7 @@ void WeatherManager::update(float duration, bool paused)
} }
if (mNextWeather != "") if (mNextWeather != "")
transition(1 - (mRemainingTransitionTime / (mWeatherSettings[mCurrentWeather].mTransitionDelta * 24.f * 3600))); transition(1 - (mRemainingTransitionTime / (findWeather(mCurrentWeather).transitionSeconds())));
else else
setResult(mCurrentWeather); setResult(mCurrentWeather);
@ -945,3 +927,23 @@ void WeatherManager::advanceTime(double hours)
{ {
mTimePassed += hours*3600; mTimePassed += hours*3600;
} }
inline void WeatherManager::addWeather(const std::string& name,
const MWWorld::Fallback& fallback,
const std::string& ambientLoopSoundID,
const std::string& particleEffect)
{
static const float fStromWindSpeed = mStore->get<ESM::GameSetting>().find("fStromWindSpeed")->getFloat();
Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, ambientLoopSoundID, particleEffect);
std::string lower = name;
lower[0] = tolower(lower[0]);
mWeatherSettings.insert(std::make_pair(lower, weather));
}
inline Weather& WeatherManager::findWeather(const std::string& name)
{
return mWeatherSettings.at(name);
}

@ -33,53 +33,55 @@ namespace MWWorld
class Fallback; class Fallback;
/// Defines a single weather setting (according to INI) /// Defines a single weather setting (according to INI)
struct Weather class Weather
{ {
public:
Weather(const std::string& name,
const MWWorld::Fallback& fallback,
float stormWindSpeed,
float rainSpeed,
const std::string& ambientLoopSoundID,
const std::string& particleEffect);
std::string mCloudTexture; std::string mCloudTexture;
// Sky (atmosphere) colors // Sky (atmosphere) colors
osg::Vec4f mSkySunriseColor, osg::Vec4f mSkySunriseColor;
mSkyDayColor, osg::Vec4f mSkyDayColor;
mSkySunsetColor, osg::Vec4f mSkySunsetColor;
mSkyNightColor; osg::Vec4f mSkyNightColor;
// Fog colors // Fog colors
osg::Vec4f mFogSunriseColor, osg::Vec4f mFogSunriseColor;
mFogDayColor, osg::Vec4f mFogDayColor;
mFogSunsetColor, osg::Vec4f mFogSunsetColor;
mFogNightColor; osg::Vec4f mFogNightColor;
// Ambient lighting colors // Ambient lighting colors
osg::Vec4f mAmbientSunriseColor, osg::Vec4f mAmbientSunriseColor;
mAmbientDayColor, osg::Vec4f mAmbientDayColor;
mAmbientSunsetColor, osg::Vec4f mAmbientSunsetColor;
mAmbientNightColor; osg::Vec4f mAmbientNightColor;
// Sun (directional) lighting colors // Sun (directional) lighting colors
osg::Vec4f mSunSunriseColor, osg::Vec4f mSunSunriseColor;
mSunDayColor, osg::Vec4f mSunDayColor;
mSunSunsetColor, osg::Vec4f mSunSunsetColor;
mSunNightColor; osg::Vec4f mSunNightColor;
// Fog depth/density // Fog depth/density
float mLandFogDayDepth, float mLandFogDayDepth;
mLandFogNightDepth; float mLandFogNightDepth;
// Color modulation for the sun itself during sunset (not completely sure) // Color modulation for the sun itself during sunset (not completely sure)
osg::Vec4f mSunDiscSunsetColor; osg::Vec4f mSunDiscSunsetColor;
// Duration of weather transition (in days)
float mTransitionDelta;
// Used by scripts to animate signs, etc based on the wind (GetWindSpeed) // Used by scripts to animate signs, etc based on the wind (GetWindSpeed)
float mWindSpeed; float mWindSpeed;
// Cloud animation speed multiplier // Cloud animation speed multiplier
float mCloudSpeed; float mCloudSpeed;
// TODO: What is this supposed to do?
float mCloudsMaximumPercent;
// Value between 0 and 1, defines the strength of the sun glare effect. // Value between 0 and 1, defines the strength of the sun glare effect.
// Also appears to modify how visible the sun, moons, and stars are for various weather effects. // Also appears to modify how visible the sun, moons, and stars are for various weather effects.
float mGlareView; float mGlareView;
@ -107,6 +109,13 @@ namespace MWWorld
// Note: For Weather Blight, there is a "Disease Chance" (=0.1) setting. But according to MWSFD this feature // Note: For Weather Blight, there is a "Disease Chance" (=0.1) setting. But according to MWSFD this feature
// is broken in the vanilla game and was disabled. // is broken in the vanilla game and was disabled.
float transitionSeconds() const;
float cloudBlendFactor(float transitionRatio) const;
private:
float mTransitionDelta;
float mCloudsMaximumPercent;
}; };
class MoonModel class MoonModel
@ -197,9 +206,7 @@ namespace MWWorld
MWBase::SoundPtr mAmbientSound; MWBase::SoundPtr mAmbientSound;
std::string mPlayingSoundID; std::string mPlayingSoundID;
MWWorld::Fallback* mFallback;
MWWorld::ESMStore* mStore; MWWorld::ESMStore* mStore;
void setFallbackWeather(Weather& weather,const std::string& name);
MWRender::RenderingManager* mRendering; MWRender::RenderingManager* mRendering;
std::map<std::string, Weather> mWeatherSettings; std::map<std::string, Weather> mWeatherSettings;
@ -251,6 +258,13 @@ namespace MWWorld
std::string mThunderSoundID3; std::string mThunderSoundID3;
MoonModel mMasser; MoonModel mMasser;
MoonModel mSecunda; MoonModel mSecunda;
void addWeather(const std::string& name,
const MWWorld::Fallback& fallback,
const std::string& ambientLoopSoundID = "",
const std::string& particleEffect = "");
Weather& findWeather(const std::string& name);
}; };
} }

Loading…
Cancel
Save