mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:23:52 +00:00
commit
e8037473ca
5 changed files with 94 additions and 33 deletions
|
@ -22,6 +22,7 @@
|
||||||
Bug #4077: Enchanted items are not recharged if they are not in the player's inventory
|
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 #4202: Open .omwaddon files without needing toopen openmw-cs first
|
||||||
Bug #4240: Ash storm origin coordinates and hand shielding animation behavior are incorrect
|
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 #4270: Closing doors while they are obstructed desyncs closing sfx
|
||||||
Bug #4276: Resizing character window differs from vanilla
|
Bug #4276: Resizing character window differs from vanilla
|
||||||
Bug #4329: Removed birthsign abilities are restored after reloading the save
|
Bug #4329: Removed birthsign abilities are restored after reloading the save
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
#include <osg/PolygonOffset>
|
#include <osg/PolygonOffset>
|
||||||
#include <osg/observer_ptr>
|
#include <osg/observer_ptr>
|
||||||
|
|
||||||
|
#include <osgParticle/BoxPlacer>
|
||||||
|
#include <osgParticle/ModularEmitter>
|
||||||
#include <osgParticle/ParticleSystem>
|
#include <osgParticle/ParticleSystem>
|
||||||
#include <osgParticle/ParticleSystemUpdater>
|
#include <osgParticle/ParticleSystemUpdater>
|
||||||
#include <osgParticle/ModularEmitter>
|
|
||||||
#include <osgParticle/BoxPlacer>
|
|
||||||
#include <osgParticle/ConstantRateCounter>
|
#include <osgParticle/ConstantRateCounter>
|
||||||
#include <osgParticle/RadialShooter>
|
#include <osgParticle/RadialShooter>
|
||||||
|
|
||||||
|
@ -1117,7 +1117,11 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana
|
||||||
, mRemainingTransitionTime(0.0f)
|
, mRemainingTransitionTime(0.0f)
|
||||||
, mRainEnabled(false)
|
, mRainEnabled(false)
|
||||||
, mRainSpeed(0)
|
, mRainSpeed(0)
|
||||||
, mRainFrequency(1)
|
, mRainDiameter(0)
|
||||||
|
, mRainMinHeight(0)
|
||||||
|
, mRainMaxHeight(0)
|
||||||
|
, mRainEntranceSpeed(1)
|
||||||
|
, mRainMaxRaindrops(0)
|
||||||
, mWindSpeed(0.f)
|
, mWindSpeed(0.f)
|
||||||
, mEnabled(true)
|
, mEnabled(true)
|
||||||
, mSunEnabled(true)
|
, mSunEnabled(true)
|
||||||
|
@ -1458,7 +1462,7 @@ void SkyManager::createRain()
|
||||||
mRainNode = new osg::Group;
|
mRainNode = new osg::Group;
|
||||||
|
|
||||||
mRainParticleSystem = new osgParticle::ParticleSystem;
|
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->setParticleAlignment(osgParticle::ParticleSystem::FIXED);
|
||||||
mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0));
|
mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0));
|
||||||
|
@ -1485,14 +1489,19 @@ void SkyManager::createRain()
|
||||||
emitter->setParticleSystem(mRainParticleSystem);
|
emitter->setParticleSystem(mRainParticleSystem);
|
||||||
|
|
||||||
osg::ref_ptr<osgParticle::BoxPlacer> placer (new osgParticle::BoxPlacer);
|
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->setYRange(-rainRange.y() / 2, rainRange.y() / 2);
|
||||||
placer->setZRange(300, 300);
|
placer->setZRange(-rainRange.z() / 2, rainRange.z() / 2);
|
||||||
emitter->setPlacer(placer);
|
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);
|
osg::ref_ptr<RainCounter> counter (new RainCounter);
|
||||||
counter->setNumberOfParticlesPerSecondToCreate(600.0);
|
counter->setNumberOfParticlesPerSecondToCreate(mRainMaxRaindrops/mRainEntranceSpeed*20);
|
||||||
emitter->setCounter(counter);
|
emitter->setCounter(counter);
|
||||||
|
mCounter = counter;
|
||||||
|
|
||||||
osg::ref_ptr<RainShooter> shooter (new RainShooter);
|
osg::ref_ptr<RainShooter> shooter (new RainShooter);
|
||||||
mRainShooter = shooter;
|
mRainShooter = shooter;
|
||||||
|
@ -1525,6 +1534,8 @@ void SkyManager::destroyRain()
|
||||||
|
|
||||||
mRootNode->removeChild(mRainNode);
|
mRootNode->removeChild(mRainNode);
|
||||||
mRainNode = nullptr;
|
mRainNode = nullptr;
|
||||||
|
mPlacer = nullptr;
|
||||||
|
mCounter = nullptr;
|
||||||
mRainParticleSystem = nullptr;
|
mRainParticleSystem = nullptr;
|
||||||
mRainShooter = nullptr;
|
mRainShooter = nullptr;
|
||||||
mRainFader = nullptr;
|
mRainFader = nullptr;
|
||||||
|
@ -1625,11 +1636,17 @@ void SkyManager::updateRainParameters()
|
||||||
{
|
{
|
||||||
if (mRainShooter)
|
if (mRainShooter)
|
||||||
{
|
{
|
||||||
// Note: an arbitrary value. An original engine seems to use a different approach to rotate raindrops.
|
float angle = -std::atan2(1, 50.f/mWindSpeed);
|
||||||
float windFactor = mWindSpeed/32.f;
|
mRainShooter->setVelocity(osg::Vec3f(0, mRainSpeed*std::sin(angle), -mRainSpeed/std::cos(angle)));
|
||||||
float angle = windFactor * osg::PI/4;
|
|
||||||
mRainShooter->setVelocity(osg::Vec3f(0, mRainSpeed * windFactor, -mRainSpeed));
|
|
||||||
mRainShooter->setAngle(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 +1663,14 @@ void SkyManager::setWeather(const WeatherResult& weather)
|
||||||
{
|
{
|
||||||
if (!mCreated) return;
|
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)
|
if (mRainEffect != weather.mRainEffect)
|
||||||
{
|
{
|
||||||
mRainEffect = weather.mRainEffect;
|
mRainEffect = weather.mRainEffect;
|
||||||
|
@ -1659,9 +1684,6 @@ void SkyManager::setWeather(const WeatherResult& weather)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mRainFrequency = weather.mRainFrequency;
|
|
||||||
mRainSpeed = weather.mRainSpeed;
|
|
||||||
mWindSpeed = weather.mWindSpeed;
|
|
||||||
updateRainParameters();
|
updateRainParameters();
|
||||||
|
|
||||||
mIsStorm = weather.mIsStorm;
|
mIsStorm = weather.mIsStorm;
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace osg
|
||||||
namespace osgParticle
|
namespace osgParticle
|
||||||
{
|
{
|
||||||
class ParticleSystem;
|
class ParticleSystem;
|
||||||
|
class BoxPlacer;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
|
@ -39,6 +40,7 @@ namespace MWRender
|
||||||
class CloudUpdater;
|
class CloudUpdater;
|
||||||
class Sun;
|
class Sun;
|
||||||
class Moon;
|
class Moon;
|
||||||
|
class RainCounter;
|
||||||
class RainShooter;
|
class RainShooter;
|
||||||
class RainFader;
|
class RainFader;
|
||||||
class AlphaFader;
|
class AlphaFader;
|
||||||
|
@ -87,8 +89,12 @@ namespace MWRender
|
||||||
std::string mRainEffect;
|
std::string mRainEffect;
|
||||||
float mEffectFade;
|
float mEffectFade;
|
||||||
|
|
||||||
|
float mRainDiameter;
|
||||||
|
float mRainMinHeight;
|
||||||
|
float mRainMaxHeight;
|
||||||
float mRainSpeed;
|
float mRainSpeed;
|
||||||
float mRainFrequency;
|
float mRainEntranceSpeed;
|
||||||
|
int mRainMaxRaindrops;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoonState
|
struct MoonState
|
||||||
|
@ -218,6 +224,8 @@ namespace MWRender
|
||||||
|
|
||||||
osg::ref_ptr<osg::Group> mRainNode;
|
osg::ref_ptr<osg::Group> mRainNode;
|
||||||
osg::ref_ptr<osgParticle::ParticleSystem> mRainParticleSystem;
|
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<RainShooter> mRainShooter;
|
||||||
osg::ref_ptr<RainFader> mRainFader;
|
osg::ref_ptr<RainFader> mRainFader;
|
||||||
|
|
||||||
|
@ -251,7 +259,11 @@ namespace MWRender
|
||||||
bool mRainEnabled;
|
bool mRainEnabled;
|
||||||
std::string mRainEffect;
|
std::string mRainEffect;
|
||||||
float mRainSpeed;
|
float mRainSpeed;
|
||||||
float mRainFrequency;
|
float mRainDiameter;
|
||||||
|
float mRainMinHeight;
|
||||||
|
float mRainMaxHeight;
|
||||||
|
float mRainEntranceSpeed;
|
||||||
|
int mRainMaxRaindrops;
|
||||||
float mWindSpeed;
|
float mWindSpeed;
|
||||||
|
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
|
|
|
@ -147,7 +147,12 @@ Weather::Weather(const std::string& name,
|
||||||
, mGlareView(Fallback::Map::getFloat("Weather_" + name + "_Glare_View"))
|
, mGlareView(Fallback::Map::getFloat("Weather_" + name + "_Glare_View"))
|
||||||
, mIsStorm(mWindSpeed > stormWindSpeed)
|
, mIsStorm(mWindSpeed > stormWindSpeed)
|
||||||
, mRainSpeed(rainSpeed)
|
, 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)
|
, mParticleEffect(particleEffect)
|
||||||
, mRainEffect(Fallback::Map::getBool("Weather_" + name + "_Using_Precip") ? "meshes\\raindrop.nif" : "")
|
, mRainEffect(Fallback::Map::getBool("Weather_" + name + "_Using_Precip") ? "meshes\\raindrop.nif" : "")
|
||||||
, mTransitionDelta(Fallback::Map::getFloat("Weather_" + name + "_Transition_Delta"))
|
, mTransitionDelta(Fallback::Map::getFloat("Weather_" + name + "_Transition_Delta"))
|
||||||
|
@ -178,15 +183,6 @@ Weather::Weather(const std::string& name,
|
||||||
|
|
||||||
if (Misc::StringUtils::ciEqual(mAmbientLoopSoundID, "None"))
|
if (Misc::StringUtils::ciEqual(mAmbientLoopSoundID, "None"))
|
||||||
mAmbientLoopSoundID.clear();
|
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
|
float Weather::transitionDelta() const
|
||||||
|
@ -1149,7 +1145,11 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam
|
||||||
mResult.mIsStorm = current.mIsStorm;
|
mResult.mIsStorm = current.mIsStorm;
|
||||||
|
|
||||||
mResult.mRainSpeed = current.mRainSpeed;
|
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.mParticleEffect = current.mParticleEffect;
|
||||||
mResult.mRainEffect = current.mRainEffect;
|
mResult.mRainEffect = current.mRainEffect;
|
||||||
|
@ -1234,16 +1234,24 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const
|
||||||
|
|
||||||
mResult.mNight = current.mNight;
|
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.mIsStorm = current.mIsStorm;
|
||||||
mResult.mParticleEffect = current.mParticleEffect;
|
mResult.mParticleEffect = current.mParticleEffect;
|
||||||
mResult.mRainEffect = current.mRainEffect;
|
mResult.mRainEffect = current.mRainEffect;
|
||||||
mResult.mRainSpeed = current.mRainSpeed;
|
mResult.mRainSpeed = current.mRainSpeed;
|
||||||
mResult.mRainFrequency = current.mRainFrequency;
|
mResult.mRainEntranceSpeed = current.mRainEntranceSpeed;
|
||||||
mResult.mAmbientSoundVolume = 1-(factor*2);
|
mResult.mAmbientSoundVolume = 1 - factor / threshold;
|
||||||
mResult.mEffectFade = mResult.mAmbientSoundVolume;
|
mResult.mEffectFade = mResult.mAmbientSoundVolume;
|
||||||
mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID;
|
mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID;
|
||||||
|
mResult.mRainDiameter = current.mRainDiameter;
|
||||||
|
mResult.mRainMinHeight = current.mRainMinHeight;
|
||||||
|
mResult.mRainMaxHeight = current.mRainMaxHeight;
|
||||||
|
mResult.mRainMaxRaindrops = current.mRainMaxRaindrops;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1251,10 +1259,15 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const
|
||||||
mResult.mParticleEffect = other.mParticleEffect;
|
mResult.mParticleEffect = other.mParticleEffect;
|
||||||
mResult.mRainEffect = other.mRainEffect;
|
mResult.mRainEffect = other.mRainEffect;
|
||||||
mResult.mRainSpeed = other.mRainSpeed;
|
mResult.mRainSpeed = other.mRainSpeed;
|
||||||
mResult.mRainFrequency = other.mRainFrequency;
|
mResult.mRainEntranceSpeed = other.mRainEntranceSpeed;
|
||||||
mResult.mAmbientSoundVolume = 2*(factor-0.5f);
|
mResult.mAmbientSoundVolume = (factor - threshold) / (1 - threshold);
|
||||||
mResult.mEffectFade = mResult.mAmbientSoundVolume;
|
mResult.mEffectFade = mResult.mAmbientSoundVolume;
|
||||||
mResult.mAmbientLoopSoundID = other.mAmbientLoopSoundID;
|
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;
|
float mRainSpeed;
|
||||||
|
|
||||||
// How often does a new rain mesh spawn?
|
// 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;
|
std::string mParticleEffect;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue