|
|
|
@ -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;
|
|
|
|
|