diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index e2f3dd82b..96771eaa3 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -7,10 +7,16 @@ #include #include #include - #include #include +#include +#include +#include +#include +#include +#include + #include #include @@ -573,6 +579,7 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana , mRainEnabled(false) , mRainSpeed(0) , mRainFrequency(1) + , mWindSpeed(0.f) , mEnabled(true) , mSunEnabled(true) { @@ -642,9 +649,112 @@ void SkyManager::create() mCreated = true; } +class RainShooter : public osgParticle::Shooter +{ +public: + RainShooter() + : mAngle(0.f) + { + } + + virtual void shoot(osgParticle::Particle* particle) const + { + particle->setVelocity(mVelocity); + particle->setAngle(osg::Vec3f(-mAngle, 0, (Misc::Rng::rollProbability() * 2 - 1) * osg::PI)); + } + + void setVelocity(const osg::Vec3f& velocity) + { + mVelocity = velocity; + } + + void setAngle(float angle) + { + mAngle = angle; + } + + virtual osg::Object* cloneType() const + { + return new RainShooter; + } + virtual osg::Object* clone(const osg::CopyOp &) const + { + return new RainShooter(*this); + } + +private: + osg::Vec3f mVelocity; + float mAngle; +}; + +void SkyManager::createRain() +{ + if (mRainNode) + return; + + mRainNode = new osg::Group; + + mRainParticleSystem = new osgParticle::ParticleSystem; + mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED); + mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0)); + mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,-1)); + + osg::ref_ptr stateset (mRainParticleSystem->getOrCreateStateSet()); + stateset->setTextureAttributeAndModes(0, mSceneManager->getTextureManager()->getTexture2D("textures/tx_raindrop_01.dds", + osg::Texture::CLAMP, osg::Texture::CLAMP), osg::StateAttribute::ON); + stateset->setNestRenderBins(false); + stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); + + osgParticle::Particle& particleTemplate = mRainParticleSystem->getDefaultParticleTemplate(); + particleTemplate.setSizeRange(osgParticle::rangef(5.f, 15.f)); + particleTemplate.setAlphaRange(osgParticle::rangef(1.f, 1.f)); + particleTemplate.setLifeTime(1); + + osg::ref_ptr emitter (new osgParticle::ModularEmitter); + emitter->setParticleSystem(mRainParticleSystem); + + osg::ref_ptr placer (new osgParticle::BoxPlacer); + placer->setXRange(-300, 300); // Rain_Diameter + placer->setYRange(-300, 300); + placer->setZRange(300, 300); + emitter->setPlacer(placer); + + osg::ref_ptr counter (new osgParticle::ConstantRateCounter); + counter->setNumberOfParticlesPerSecondToCreate(600.0); + emitter->setCounter(counter); + + osg::ref_ptr shooter (new RainShooter); + mRainShooter = shooter; + emitter->setShooter(shooter); + + osg::ref_ptr updater (new osgParticle::ParticleSystemUpdater); + updater->addParticleSystem(mRainParticleSystem); + + osg::ref_ptr geode (new osg::Geode); + geode->addDrawable(mRainParticleSystem); + + mRainNode->addChild(emitter); + mRainNode->addChild(geode); + mRainNode->addChild(updater); + + mRootNode->addChild(mRainNode); +} + +void SkyManager::destroyRain() +{ + if (!mRainNode) + return; + + mRootNode->removeChild(mRainNode); + mRainNode = NULL; + mRainParticleSystem = NULL; + mRainShooter = NULL; +} + SkyManager::~SkyManager() { - clearRain(); if (mRootNode) { mRootNode->getParent(0)->removeChild(mRootNode); @@ -664,14 +774,6 @@ int SkyManager::getSecundaPhase() const return mSecunda->getPhaseInt(); } -void SkyManager::clearRain() -{ -} - -void SkyManager::updateRain(float dt) -{ -} - void SkyManager::update(float duration) { if (!mEnabled) return; @@ -688,8 +790,6 @@ void SkyManager::update(float duration) else mCloudNode->setAttitude(osg::Quat()); - updateRain(duration); - // UV Scroll the clouds mCloudAnimationTimer += duration * mCloudSpeed * 0.003; mCloudUpdater->setAnimationTimer(mCloudAnimationTimer); @@ -736,9 +836,6 @@ void SkyManager::setEnabled(bool enabled) if (enabled && !mCreated) create(); - if (!enabled) - clearRain(); - mRootNode->setNodeMask(enabled ? Mask_Sky : 0); mEnabled = enabled; @@ -750,14 +847,38 @@ void SkyManager::setMoonColour (bool red) mSecunda->setColor(red ? mMoonScriptColor : osg::Vec4f(1,1,1,1)); } +void SkyManager::updateRainParameters() +{ + if (mRainShooter) + { + float angle = mWindSpeed/2.f * osg::PI/4; + mRainShooter->setVelocity(osg::Vec3f(0, mRainSpeed * mWindSpeed / 2.f, -mRainSpeed)); + mRainShooter->setAngle(angle); + } +} + void SkyManager::setWeather(const MWWorld::WeatherResult& weather) { if (!mCreated) return; - mRainEffect = weather.mRainEffect; - mRainEnabled = !mRainEffect.empty(); + if (mRainEffect != weather.mRainEffect) + { + mRainEffect = weather.mRainEffect; + if (!mRainEffect.empty()) + { + createRain(); + } + else + { + destroyRain(); + } + } + mRainFrequency = weather.mRainFrequency; mRainSpeed = weather.mRainSpeed; + mWindSpeed = weather.mWindSpeed; + updateRainParameters(); + mIsStorm = weather.mIsStorm; if (mCurrentParticleEffect != weather.mParticleEffect) diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index b05845e53..f9b9407ec 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -12,6 +12,11 @@ namespace osg class Material; } +namespace osgParticle +{ + class ParticleSystem; +} + namespace Resource { class SceneManager; @@ -24,6 +29,7 @@ namespace MWRender class CloudUpdater; class Sun; class Moon; + class RainShooter; class SkyManager { @@ -87,8 +93,9 @@ namespace MWRender void create(); ///< no need to call this, automatically done on first enable() - void updateRain(float dt); - void clearRain(); + void createRain(); + void destroyRain(); + void updateRainParameters(); Resource::SceneManager* mSceneManager; @@ -116,6 +123,10 @@ namespace MWRender std::auto_ptr mMasser; std::auto_ptr mSecunda; + osg::ref_ptr mRainNode; + osg::ref_ptr mRainParticleSystem; + osg::ref_ptr mRainShooter; + bool mCreated; bool mIsStorm; @@ -151,6 +162,7 @@ namespace MWRender std::string mRainEffect; float mRainSpeed; float mRainFrequency; + float mWindSpeed; bool mEnabled; bool mSunEnabled;