Use rain settings from openmw.cfg (bug #4262)

pull/2559/head
Andrei Kortunov 5 years ago
parent 9c457c7fc0
commit 606b73ee96

@ -22,6 +22,7 @@
Bug #4077: Enchanted items are not recharged if they are not in the player's inventory
Bug #4202: Open .omwaddon files without needing toopen openmw-cs first
Bug #4240: Ash storm origin coordinates and hand shielding animation behavior are incorrect
Bug #4262: Rain settings are hardcoded
Bug #4270: Closing doors while they are obstructed desyncs closing sfx
Bug #4276: Resizing character window differs from vanilla
Bug #4329: Removed birthsign abilities are restored after reloading the save

@ -18,10 +18,9 @@
#include <osg/PolygonOffset>
#include <osg/observer_ptr>
#include <osgParticle/ModularEmitter>
#include <osgParticle/ParticleSystem>
#include <osgParticle/ParticleSystemUpdater>
#include <osgParticle/ModularEmitter>
#include <osgParticle/BoxPlacer>
#include <osgParticle/ConstantRateCounter>
#include <osgParticle/RadialShooter>
@ -1117,7 +1116,11 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana
, mRemainingTransitionTime(0.0f)
, mRainEnabled(false)
, mRainSpeed(0)
, mRainFrequency(1)
, mRainDiameter(0)
, mRainMinHeight(0)
, mRainMaxHeight(0)
, mRainEntranceSpeed(1)
, mRainMaxRaindrops(0)
, mWindSpeed(0.f)
, mEnabled(true)
, mSunEnabled(true)
@ -1458,7 +1461,7 @@ void SkyManager::createRain()
mRainNode = new osg::Group;
mRainParticleSystem = new osgParticle::ParticleSystem;
osg::Vec3 rainRange = osg::Vec3(600,600,600);
osg::Vec3 rainRange = osg::Vec3(mRainDiameter, mRainDiameter, (mRainMinHeight+mRainMaxHeight)/2.f);
mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED);
mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0));
@ -1485,14 +1488,19 @@ void SkyManager::createRain()
emitter->setParticleSystem(mRainParticleSystem);
osg::ref_ptr<osgParticle::BoxPlacer> placer (new osgParticle::BoxPlacer);
placer->setXRange(-rainRange.x() / 2, rainRange.x() / 2); // Rain_Diameter
placer->setXRange(-rainRange.x() / 2, rainRange.x() / 2);
placer->setYRange(-rainRange.y() / 2, rainRange.y() / 2);
placer->setZRange(300, 300);
placer->setZRange(-rainRange.z() / 2, rainRange.z() / 2);
emitter->setPlacer(placer);
mPlacer = placer;
// FIXME: vanilla engine does not use a particle system to handle rain, it uses a NIF-file with 20 raindrops in it.
// It spawns the (maxRaindrops-getParticleSystem()->numParticles())*dt/rainEntranceSpeed batches every frame (near 1-2).
// Since the rain is a regular geometry, it produces water ripples, also in theory it can be removed if collides with something.
osg::ref_ptr<RainCounter> counter (new RainCounter);
counter->setNumberOfParticlesPerSecondToCreate(600.0);
counter->setNumberOfParticlesPerSecondToCreate(mRainMaxRaindrops/mRainEntranceSpeed*20);
emitter->setCounter(counter);
mCounter = counter;
osg::ref_ptr<RainShooter> shooter (new RainShooter);
mRainShooter = shooter;
@ -1525,6 +1533,8 @@ void SkyManager::destroyRain()
mRootNode->removeChild(mRainNode);
mRainNode = nullptr;
mPlacer = nullptr;
mCounter = nullptr;
mRainParticleSystem = nullptr;
mRainShooter = nullptr;
mRainFader = nullptr;
@ -1625,11 +1635,17 @@ void SkyManager::updateRainParameters()
{
if (mRainShooter)
{
// Note: an arbitrary value. An original engine seems to use a different approach to rotate raindrops.
float windFactor = mWindSpeed/32.f;
float angle = windFactor * osg::PI/4;
mRainShooter->setVelocity(osg::Vec3f(0, mRainSpeed * windFactor, -mRainSpeed));
float angle = -std::atan2(1, 50.f/mWindSpeed);
mRainShooter->setVelocity(osg::Vec3f(0, mRainSpeed*std::sin(angle), -mRainSpeed/std::cos(angle)));
mRainShooter->setAngle(angle);
osg::Vec3 rainRange = osg::Vec3(mRainDiameter, mRainDiameter, (mRainMinHeight+mRainMaxHeight)/2.f);
mPlacer->setXRange(-rainRange.x() / 2, rainRange.x() / 2);
mPlacer->setYRange(-rainRange.y() / 2, rainRange.y() / 2);
mPlacer->setZRange(-rainRange.z() / 2, rainRange.z() / 2);
mCounter->setNumberOfParticlesPerSecondToCreate(mRainMaxRaindrops/mRainEntranceSpeed*20);
}
}
@ -1646,6 +1662,14 @@ void SkyManager::setWeather(const WeatherResult& weather)
{
if (!mCreated) return;
mRainEntranceSpeed = weather.mRainEntranceSpeed;
mRainMaxRaindrops = weather.mRainMaxRaindrops;
mRainDiameter = weather.mRainDiameter;
mRainMinHeight = weather.mRainMinHeight;
mRainMaxHeight = weather.mRainMaxHeight;
mRainSpeed = weather.mRainSpeed;
mWindSpeed = weather.mWindSpeed;
if (mRainEffect != weather.mRainEffect)
{
mRainEffect = weather.mRainEffect;
@ -1659,9 +1683,6 @@ void SkyManager::setWeather(const WeatherResult& weather)
}
}
mRainFrequency = weather.mRainFrequency;
mRainSpeed = weather.mRainSpeed;
mWindSpeed = weather.mWindSpeed;
updateRainParameters();
mIsStorm = weather.mIsStorm;

@ -9,6 +9,8 @@
#include <osg/Vec4f>
#include <osg/Uniform>
#include <osgParticle/BoxPlacer>
namespace osg
{
class Camera;
@ -39,6 +41,7 @@ namespace MWRender
class CloudUpdater;
class Sun;
class Moon;
class RainCounter;
class RainShooter;
class RainFader;
class AlphaFader;
@ -87,8 +90,12 @@ namespace MWRender
std::string mRainEffect;
float mEffectFade;
float mRainDiameter;
float mRainMinHeight;
float mRainMaxHeight;
float mRainSpeed;
float mRainFrequency;
float mRainEntranceSpeed;
int mRainMaxRaindrops;
};
struct MoonState
@ -218,6 +225,8 @@ namespace MWRender
osg::ref_ptr<osg::Group> mRainNode;
osg::ref_ptr<osgParticle::ParticleSystem> mRainParticleSystem;
osg::ref_ptr<osgParticle::BoxPlacer> mPlacer;
osg::ref_ptr<RainCounter> mCounter;
osg::ref_ptr<RainShooter> mRainShooter;
osg::ref_ptr<RainFader> mRainFader;
@ -251,7 +260,11 @@ namespace MWRender
bool mRainEnabled;
std::string mRainEffect;
float mRainSpeed;
float mRainFrequency;
float mRainDiameter;
float mRainMinHeight;
float mRainMaxHeight;
float mRainEntranceSpeed;
int mRainMaxRaindrops;
float mWindSpeed;
bool mEnabled;

@ -147,7 +147,12 @@ Weather::Weather(const std::string& name,
, mGlareView(Fallback::Map::getFloat("Weather_" + name + "_Glare_View"))
, mIsStorm(mWindSpeed > stormWindSpeed)
, mRainSpeed(rainSpeed)
, mRainFrequency(Fallback::Map::getFloat("Weather_" + name + "_Rain_Entrance_Speed"))
, mRainEntranceSpeed(Fallback::Map::getFloat("Weather_" + name + "_Rain_Entrance_Speed"))
, mRainMaxRaindrops(Fallback::Map::getFloat("Weather_" + name + "_Max_Raindrops"))
, mRainDiameter(Fallback::Map::getFloat("Weather_" + name + "_Rain_Diameter"))
, mRainThreshold(Fallback::Map::getFloat("Weather_" + name + "_Rain_Threshold"))
, mRainMinHeight(Fallback::Map::getFloat("Weather_" + name + "_Rain_Height_Min"))
, mRainMaxHeight(Fallback::Map::getFloat("Weather_" + name + "_Rain_Height_Max"))
, mParticleEffect(particleEffect)
, mRainEffect(Fallback::Map::getBool("Weather_" + name + "_Using_Precip") ? "meshes\\raindrop.nif" : "")
, mTransitionDelta(Fallback::Map::getFloat("Weather_" + name + "_Transition_Delta"))
@ -178,15 +183,6 @@ Weather::Weather(const std::string& name,
if (Misc::StringUtils::ciEqual(mAmbientLoopSoundID, "None"))
mAmbientLoopSoundID.clear();
/*
Unhandled:
Rain Diameter=600 ?
Rain Height Min=200 ?
Rain Height Max=700 ?
Rain Threshold=0.6 ?
Max Raindrops=650 ?
*/
}
float Weather::transitionDelta() const
@ -1149,7 +1145,11 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam
mResult.mIsStorm = current.mIsStorm;
mResult.mRainSpeed = current.mRainSpeed;
mResult.mRainFrequency = current.mRainFrequency;
mResult.mRainEntranceSpeed = current.mRainEntranceSpeed;
mResult.mRainDiameter = current.mRainDiameter;
mResult.mRainMinHeight = current.mRainMinHeight;
mResult.mRainMaxHeight = current.mRainMaxHeight;
mResult.mRainMaxRaindrops = current.mRainMaxRaindrops;
mResult.mParticleEffect = current.mParticleEffect;
mResult.mRainEffect = current.mRainEffect;
@ -1234,16 +1234,24 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const
mResult.mNight = current.mNight;
if(factor < 0.5)
float threshold = mWeatherSettings[mNextWeather].mRainThreshold;
if (threshold <= 0)
threshold = 0.5f;
if(factor < threshold)
{
mResult.mIsStorm = current.mIsStorm;
mResult.mParticleEffect = current.mParticleEffect;
mResult.mRainEffect = current.mRainEffect;
mResult.mRainSpeed = current.mRainSpeed;
mResult.mRainFrequency = current.mRainFrequency;
mResult.mAmbientSoundVolume = 1-(factor*2);
mResult.mRainEntranceSpeed = current.mRainEntranceSpeed;
mResult.mAmbientSoundVolume = 1 - factor / threshold;
mResult.mEffectFade = mResult.mAmbientSoundVolume;
mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID;
mResult.mRainDiameter = current.mRainDiameter;
mResult.mRainMinHeight = current.mRainMinHeight;
mResult.mRainMaxHeight = current.mRainMaxHeight;
mResult.mRainMaxRaindrops = current.mRainMaxRaindrops;
}
else
{
@ -1251,10 +1259,15 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const
mResult.mParticleEffect = other.mParticleEffect;
mResult.mRainEffect = other.mRainEffect;
mResult.mRainSpeed = other.mRainSpeed;
mResult.mRainFrequency = other.mRainFrequency;
mResult.mAmbientSoundVolume = 2*(factor-0.5f);
mResult.mRainEntranceSpeed = other.mRainEntranceSpeed;
mResult.mAmbientSoundVolume = (factor - threshold) / (1 - threshold);
mResult.mEffectFade = mResult.mAmbientSoundVolume;
mResult.mAmbientLoopSoundID = other.mAmbientLoopSoundID;
mResult.mRainDiameter = other.mRainDiameter;
mResult.mRainMinHeight = other.mRainMinHeight;
mResult.mRainMaxHeight = other.mRainMaxHeight;
mResult.mRainMaxRaindrops = other.mRainMaxRaindrops;
}
}

@ -170,7 +170,20 @@ namespace MWWorld
float mRainSpeed;
// How often does a new rain mesh spawn?
float mRainFrequency;
float mRainEntranceSpeed;
// Maximum count of rain particles
int mRainMaxRaindrops;
// Radius of rain effect
float mRainDiameter;
// Transition threshold to spawn rain
float mRainThreshold;
// Height of rain particles spawn
float mRainMinHeight;
float mRainMaxHeight;
std::string mParticleEffect;

Loading…
Cancel
Save