Rain effect

c++11
scrawl 10 years ago
parent 5ac502d104
commit 3a21f05f6e

@ -7,10 +7,16 @@
#include <osg/Material> #include <osg/Material>
#include <osg/Geometry> #include <osg/Geometry>
#include <osg/PositionAttitudeTransform> #include <osg/PositionAttitudeTransform>
#include <osg/TexEnvCombine> #include <osg/TexEnvCombine>
#include <osg/TexMat> #include <osg/TexMat>
#include <osgParticle/ParticleSystem>
#include <osgParticle/ParticleSystemUpdater>
#include <osgParticle/ModularEmitter>
#include <osgParticle/BoxPlacer>
#include <osgParticle/ConstantRateCounter>
#include <osgParticle/RadialShooter>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <components/misc/rng.hpp> #include <components/misc/rng.hpp>
@ -573,6 +579,7 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana
, mRainEnabled(false) , mRainEnabled(false)
, mRainSpeed(0) , mRainSpeed(0)
, mRainFrequency(1) , mRainFrequency(1)
, mWindSpeed(0.f)
, mEnabled(true) , mEnabled(true)
, mSunEnabled(true) , mSunEnabled(true)
{ {
@ -642,9 +649,112 @@ void SkyManager::create()
mCreated = true; 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<osg::StateSet> 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<osgParticle::ModularEmitter> emitter (new osgParticle::ModularEmitter);
emitter->setParticleSystem(mRainParticleSystem);
osg::ref_ptr<osgParticle::BoxPlacer> placer (new osgParticle::BoxPlacer);
placer->setXRange(-300, 300); // Rain_Diameter
placer->setYRange(-300, 300);
placer->setZRange(300, 300);
emitter->setPlacer(placer);
osg::ref_ptr<osgParticle::ConstantRateCounter> counter (new osgParticle::ConstantRateCounter);
counter->setNumberOfParticlesPerSecondToCreate(600.0);
emitter->setCounter(counter);
osg::ref_ptr<RainShooter> shooter (new RainShooter);
mRainShooter = shooter;
emitter->setShooter(shooter);
osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater (new osgParticle::ParticleSystemUpdater);
updater->addParticleSystem(mRainParticleSystem);
osg::ref_ptr<osg::Geode> 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() SkyManager::~SkyManager()
{ {
clearRain();
if (mRootNode) if (mRootNode)
{ {
mRootNode->getParent(0)->removeChild(mRootNode); mRootNode->getParent(0)->removeChild(mRootNode);
@ -664,14 +774,6 @@ int SkyManager::getSecundaPhase() const
return mSecunda->getPhaseInt(); return mSecunda->getPhaseInt();
} }
void SkyManager::clearRain()
{
}
void SkyManager::updateRain(float dt)
{
}
void SkyManager::update(float duration) void SkyManager::update(float duration)
{ {
if (!mEnabled) return; if (!mEnabled) return;
@ -688,8 +790,6 @@ void SkyManager::update(float duration)
else else
mCloudNode->setAttitude(osg::Quat()); mCloudNode->setAttitude(osg::Quat());
updateRain(duration);
// UV Scroll the clouds // UV Scroll the clouds
mCloudAnimationTimer += duration * mCloudSpeed * 0.003; mCloudAnimationTimer += duration * mCloudSpeed * 0.003;
mCloudUpdater->setAnimationTimer(mCloudAnimationTimer); mCloudUpdater->setAnimationTimer(mCloudAnimationTimer);
@ -736,9 +836,6 @@ void SkyManager::setEnabled(bool enabled)
if (enabled && !mCreated) if (enabled && !mCreated)
create(); create();
if (!enabled)
clearRain();
mRootNode->setNodeMask(enabled ? Mask_Sky : 0); mRootNode->setNodeMask(enabled ? Mask_Sky : 0);
mEnabled = enabled; mEnabled = enabled;
@ -750,14 +847,38 @@ void SkyManager::setMoonColour (bool red)
mSecunda->setColor(red ? mMoonScriptColor : osg::Vec4f(1,1,1,1)); 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) void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
{ {
if (!mCreated) return; if (!mCreated) return;
mRainEffect = weather.mRainEffect; if (mRainEffect != weather.mRainEffect)
mRainEnabled = !mRainEffect.empty(); {
mRainEffect = weather.mRainEffect;
if (!mRainEffect.empty())
{
createRain();
}
else
{
destroyRain();
}
}
mRainFrequency = weather.mRainFrequency; mRainFrequency = weather.mRainFrequency;
mRainSpeed = weather.mRainSpeed; mRainSpeed = weather.mRainSpeed;
mWindSpeed = weather.mWindSpeed;
updateRainParameters();
mIsStorm = weather.mIsStorm; mIsStorm = weather.mIsStorm;
if (mCurrentParticleEffect != weather.mParticleEffect) if (mCurrentParticleEffect != weather.mParticleEffect)

@ -12,6 +12,11 @@ namespace osg
class Material; class Material;
} }
namespace osgParticle
{
class ParticleSystem;
}
namespace Resource namespace Resource
{ {
class SceneManager; class SceneManager;
@ -24,6 +29,7 @@ namespace MWRender
class CloudUpdater; class CloudUpdater;
class Sun; class Sun;
class Moon; class Moon;
class RainShooter;
class SkyManager class SkyManager
{ {
@ -87,8 +93,9 @@ namespace MWRender
void create(); void create();
///< no need to call this, automatically done on first enable() ///< no need to call this, automatically done on first enable()
void updateRain(float dt); void createRain();
void clearRain(); void destroyRain();
void updateRainParameters();
Resource::SceneManager* mSceneManager; Resource::SceneManager* mSceneManager;
@ -116,6 +123,10 @@ namespace MWRender
std::auto_ptr<Moon> mMasser; std::auto_ptr<Moon> mMasser;
std::auto_ptr<Moon> mSecunda; std::auto_ptr<Moon> mSecunda;
osg::ref_ptr<osg::Group> mRainNode;
osg::ref_ptr<osgParticle::ParticleSystem> mRainParticleSystem;
osg::ref_ptr<RainShooter> mRainShooter;
bool mCreated; bool mCreated;
bool mIsStorm; bool mIsStorm;
@ -151,6 +162,7 @@ namespace MWRender
std::string mRainEffect; std::string mRainEffect;
float mRainSpeed; float mRainSpeed;
float mRainFrequency; float mRainFrequency;
float mWindSpeed;
bool mEnabled; bool mEnabled;
bool mSunEnabled; bool mSunEnabled;

Loading…
Cancel
Save