Merge pull request #753 from slothlife/thunderstorm-support

Improve thunderstorm support.
sceneinput
scrawl 9 years ago
commit cd0f8e556b

@ -1181,20 +1181,6 @@ void SkyManager::setSecundaState(const MoonState& state)
mSecunda->setState(state);
}
void SkyManager::setLightningStrength(const float factor)
{
if (!mCreated) return;
/*
if (factor > 0.f)
{
mLightning->setDiffuseColour (ColourValue(2*factor, 2*factor, 2*factor));
mLightning->setVisible(true);
}
else
mLightning->setVisible(false);
*/
}
void SkyManager::setDate(int day, int month)
{
mDay = day;

@ -140,8 +140,6 @@ namespace MWRender
void setMasserState(const MoonState& state);
void setSecundaState(const MoonState& state);
void setLightningStrength(const float factor);
void setGlare(const float glare);
void setGlareEnabled(bool enabled);

@ -80,15 +80,24 @@ Weather::Weather(const std::string& name,
, 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"))
, mThunderFrequency(fallback.getFallbackFloat("Weather_" + name + "_Thunder_Frequency"))
, mThunderThreshold(fallback.getFallbackFloat("Weather_" + name + "_Thunder_Threshold"))
, mThunderSoundID()
, mFlashDecrement(fallback.getFallbackFloat("Weather_" + name + "_Flash_Decrement"))
, mFlashBrightness(0.0f)
{
/*
Unhandled:
Rain Diameter=600 ?
Rain Height Min=200 ?
Rain Height Max=700 ?
Rain Threshold=0.6 ?
Max Raindrops=650 ?
*/
mThunderSoundID[0] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_0");
mThunderSoundID[1] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_1");
mThunderSoundID[2] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_2");
mThunderSoundID[3] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_3");
/*
Unhandled:
Rain Diameter=600 ?
Rain Height Min=200 ?
Rain Height Max=700 ?
Rain Threshold=0.6 ?
Max Raindrops=650 ?
*/
}
float Weather::transitionDelta() const
@ -98,12 +107,66 @@ float Weather::transitionDelta() const
return mTransitionDelta;
}
float Weather::cloudBlendFactor(float transitionRatio) const
float Weather::cloudBlendFactor(const float transitionRatio) const
{
// Clouds Maximum Percent affects how quickly the sky transitions from one sky texture to the next.
return transitionRatio / mCloudsMaximumPercent;
}
float Weather::calculateThunder(const float transitionRatio, const float elapsedSeconds, const bool isPaused)
{
// When paused, the flash brightness remains the same and no new strikes can occur.
if(!isPaused)
{
// Morrowind doesn't appear to do any calculations unless the transition ratio is higher than the Thunder Threshold.
if(transitionRatio >= mThunderThreshold && mThunderFrequency > 0.0f)
{
flashDecrement(elapsedSeconds);
if(Misc::Rng::rollProbability() <= thunderChance(transitionRatio, elapsedSeconds))
{
lightningAndThunder();
}
}
else
{
mFlashBrightness = 0.0f;
}
}
return mFlashBrightness;
}
inline void Weather::flashDecrement(const float elapsedSeconds)
{
// The Flash Decrement is measured in whole units per second. This means that if the flash brightness was
// currently 1.0, then it should take approximately 0.25 seconds to decay to 0.0 (the minimum).
float decrement = mFlashDecrement * elapsedSeconds;
mFlashBrightness = decrement > mFlashBrightness ? 0.0f : mFlashBrightness - decrement;
}
inline float Weather::thunderChance(const float transitionRatio, const float elapsedSeconds) const
{
// This formula is reversed from the observation that with Thunder Frequency set to 1, there are roughly 10 strikes
// per minute. It doesn't appear to be tied to in game time as Timescale doesn't affect it. Various values of
// Thunder Frequency seem to change the average number of strikes in a linear fashion.. During a transition, it appears to
// scaled based on how far past it is past the Thunder Threshold.
float scaleFactor = (transitionRatio - mThunderThreshold) / (1.0f - mThunderThreshold);
return ((mThunderFrequency * 10.0f) / 60.0f) * elapsedSeconds * scaleFactor;
}
inline void Weather::lightningAndThunder(void)
{
// Morrowind seems to vary the intensity of the brightness based on which of the four sound IDs it selects.
// They appear to go from 0 (brightest, closest) to 3 (faintest, farthest). The value of 0.25 per distance
// was derived by setting the Flash Decrement to 0.1 and measuring how long each value took to decay to 0.
// TODO: Determine the distribution of each distance to see if it's evenly weighted.
unsigned int distance = Misc::Rng::rollDice(4);
// Flash brightness appears additive, since if multiple strikes occur, it takes longer for it to decay to 0.
mFlashBrightness += 1 - (distance * 0.25f);
MWBase::Environment::get().getSoundManager()->playSound(mThunderSoundID[distance], 1.0, 1.0);
}
RegionWeather::RegionWeather(const ESM::Region& region)
: mWeather(invalidWeatherID)
, mChances()
@ -378,19 +441,9 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const MWWo
, mWeatherSettings()
, mMasser("Masser", fallback)
, mSecunda("Secunda", fallback)
, mThunderFrequency(fallback.getFallbackFloat("Weather_Thunderstorm_Thunder_Frequency"))
, mThunderThreshold(fallback.getFallbackFloat("Weather_Thunderstorm_Thunder_Threshold"))
, mThunderSoundID0(fallback.getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_0"))
, mThunderSoundID1(fallback.getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_1"))
, mThunderSoundID2(fallback.getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_2"))
, mThunderSoundID3(fallback.getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_3"))
, mWindSpeed(0.f)
, mIsStorm(false)
, mStormDirection(0,1,0)
, mThunderSoundDelay(0.25)
, mThunderFlash(0)
, mThunderChance(0)
, mThunderChanceNeeded(50)
, mCurrentRegion()
, mTimePassed(0)
, mFastForward(false)
@ -515,12 +568,11 @@ void WeatherManager::update(float duration, bool paused)
if(!exterior)
{
mRendering.setSkyEnabled(false);
//mRendering->getSkyManager()->setLightningStrength(0.f);
stopSounds();
return;
}
calculateWeatherResult(time.getHour());
calculateWeatherResult(time.getHour(), duration, paused);
mWindSpeed = mResult.mWindSpeed;
mIsStorm = mResult.mIsStorm;
@ -536,8 +588,6 @@ void WeatherManager::update(float duration, bool paused)
mRendering.getSkyManager()->setStormDirection(mStormDirection);
}
mRendering.configureFog(mResult.mFogDepth, mResult.mFogColor);
// disable sun during night
if (time.getHour() >= mNightStart || time.getHour() <= mSunriseTime)
mRendering.getSkyManager()->sunDisable();
@ -577,56 +627,7 @@ void WeatherManager::update(float duration, bool paused)
mRendering.getSkyManager()->setMasserState(mMasser.calculateState(time));
mRendering.getSkyManager()->setSecundaState(mSecunda.calculateState(time));
if (!paused)
{
if(mCurrentWeather == 5 && !inTransition())
{
if (mThunderFlash > 0)
{
// play the sound after a delay
mThunderSoundDelay -= duration;
if (mThunderSoundDelay <= 0)
{
// pick a random sound
int sound = Misc::Rng::rollDice(4);
std::string* soundName = NULL;
if (sound == 0) soundName = &mThunderSoundID0;
else if (sound == 1) soundName = &mThunderSoundID1;
else if (sound == 2) soundName = &mThunderSoundID2;
else if (sound == 3) soundName = &mThunderSoundID3;
if (soundName)
MWBase::Environment::get().getSoundManager()->playSound(*soundName, 1.0, 1.0);
mThunderSoundDelay = 1000;
}
mThunderFlash -= duration;
//if (mThunderFlash > 0)
//mRendering->getSkyManager()->setLightningStrength( mThunderFlash / mThunderThreshold );
//else
{
mThunderChanceNeeded = static_cast<float>(Misc::Rng::rollDice(100));
mThunderChance = 0;
//mRendering->getSkyManager()->setLightningStrength( 0.f );
}
}
else
{
// no thunder active
mThunderChance += duration*4; // chance increases by 4 percent every second
if (mThunderChance >= mThunderChanceNeeded)
{
mThunderFlash = mThunderThreshold;
//mRendering->getSkyManager()->setLightningStrength( mThunderFlash / mThunderThreshold );
mThunderSoundDelay = 0.25;
}
}
}
//else
//mRendering->getSkyManager()->setLightningStrength(0.f);
}
mRendering.configureFog(mResult.mFogDepth, mResult.mFogColor);
mRendering.setAmbientColour(mResult.mAmbientColor);
mRendering.setSunColour(mResult.mSunColor);
@ -765,10 +766,6 @@ void WeatherManager::clear()
{
stopSounds();
mThunderFlash = 0.0;
mThunderChance = 0.0;
mThunderChanceNeeded = 50.0;
mCurrentRegion = "";
mTimePassed = 0.0f;
mWeatherUpdateTime = 0.0f;
@ -921,16 +918,32 @@ inline void WeatherManager::addWeatherTransition(const int weatherID)
}
}
inline void WeatherManager::calculateWeatherResult(const float gameHour)
inline void WeatherManager::calculateWeatherResult(const float gameHour,
const float elapsedSeconds,
const bool isPaused)
{
float flash = 0.0f;
if(!inTransition())
{
calculateResult(mCurrentWeather, gameHour);
flash = mWeatherSettings[mCurrentWeather].calculateThunder(1.0f, elapsedSeconds, isPaused);
}
else
{
calculateTransitionResult(1 - mTransitionFactor, gameHour);
float currentFlash = mWeatherSettings[mCurrentWeather].calculateThunder(mTransitionFactor,
elapsedSeconds,
isPaused);
float nextFlash = mWeatherSettings[mNextWeather].calculateThunder(1 - mTransitionFactor,
elapsedSeconds,
isPaused);
flash = currentFlash + nextFlash;
}
osg::Vec4f flashColor(flash, flash, flash, 0.0f);
mResult.mFogColor += flashColor;
mResult.mAmbientColor += flashColor;
mResult.mSunColor += flashColor;
}
inline void WeatherManager::calculateResult(const int weatherID, const float gameHour)

@ -113,11 +113,27 @@ namespace MWWorld
// is broken in the vanilla game and was disabled.
float transitionDelta() const;
float cloudBlendFactor(float transitionRatio) const;
float cloudBlendFactor(const float transitionRatio) const;
float calculateThunder(const float transitionRatio, const float elapsedSeconds, const bool isPaused);
private:
float mTransitionDelta;
float mCloudsMaximumPercent;
// Note: In MW, only thunderstorms support these attributes, but in the interest of making weather more
// flexible, these settings are imported for all weather types. Only thunderstorms will normally have any
// non-zero values.
float mThunderFrequency;
float mThunderThreshold;
std::string mThunderSoundID[4];
float mFlashDecrement;
float mFlashBrightness;
void flashDecrement(const float elapsedSeconds);
float thunderChance(const float transitionRatio, const float elapsedSeconds) const;
void lightningAndThunder(void);
};
/// A class for storing a region's weather.
@ -242,22 +258,10 @@ namespace MWWorld
MoonModel mMasser;
MoonModel mSecunda;
float mThunderFrequency;
float mThunderThreshold;
std::string mThunderSoundID0;
std::string mThunderSoundID1;
std::string mThunderSoundID2;
std::string mThunderSoundID3;
float mWindSpeed;
bool mIsStorm;
osg::Vec3f mStormDirection;
float mThunderSoundDelay;
float mThunderFlash;
float mThunderChance;
float mThunderChanceNeeded;
std::string mCurrentRegion;
float mTimePassed;
bool mFastForward;
@ -288,7 +292,7 @@ namespace MWWorld
bool inTransition();
void addWeatherTransition(const int weatherID);
void calculateWeatherResult(const float gameHour);
void calculateWeatherResult(const float gameHour, const float elapsedSeconds, const bool isPaused);
void calculateResult(const int weatherID, const float gameHour);
void calculateTransitionResult(const float factor, const float gameHour);
};

Loading…
Cancel
Save