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 #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,10 @@
|
|||
#include <osg/PolygonOffset>
|
||||
#include <osg/observer_ptr>
|
||||
|
||||
#include <osgParticle/BoxPlacer>
|
||||
#include <osgParticle/ModularEmitter>
|
||||
#include <osgParticle/ParticleSystem>
|
||||
#include <osgParticle/ParticleSystemUpdater>
|
||||
#include <osgParticle/ModularEmitter>
|
||||
#include <osgParticle/BoxPlacer>
|
||||
#include <osgParticle/ConstantRateCounter>
|
||||
#include <osgParticle/RadialShooter>
|
||||
|
||||
|
@ -1117,7 +1117,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 +1462,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 +1489,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 +1534,8 @@ void SkyManager::destroyRain()
|
|||
|
||||
mRootNode->removeChild(mRainNode);
|
||||
mRainNode = nullptr;
|
||||
mPlacer = nullptr;
|
||||
mCounter = nullptr;
|
||||
mRainParticleSystem = nullptr;
|
||||
mRainShooter = nullptr;
|
||||
mRainFader = nullptr;
|
||||
|
@ -1625,11 +1636,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 +1663,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 +1684,6 @@ void SkyManager::setWeather(const WeatherResult& weather)
|
|||
}
|
||||
}
|
||||
|
||||
mRainFrequency = weather.mRainFrequency;
|
||||
mRainSpeed = weather.mRainSpeed;
|
||||
mWindSpeed = weather.mWindSpeed;
|
||||
updateRainParameters();
|
||||
|
||||
mIsStorm = weather.mIsStorm;
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace osg
|
|||
namespace osgParticle
|
||||
{
|
||||
class ParticleSystem;
|
||||
class BoxPlacer;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
|
@ -39,6 +40,7 @@ namespace MWRender
|
|||
class CloudUpdater;
|
||||
class Sun;
|
||||
class Moon;
|
||||
class RainCounter;
|
||||
class RainShooter;
|
||||
class RainFader;
|
||||
class AlphaFader;
|
||||
|
@ -87,8 +89,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 +224,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 +259,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…
Reference in a new issue