use operator instead of drawcallback

pull/313/head
Miloslav Číž 7 years ago committed by Miloslav Číž
parent 65977b910e
commit af6eeddbe5

@ -256,6 +256,7 @@ namespace MWRender
mRootNode->getOrCreateStateSet()->addUniform(mUniformRainIntensity); mRootNode->getOrCreateStateSet()->addUniform(mUniformRainIntensity);
mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager())); mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager()));
mSky->setCamera(mViewer->getCamera());
source->setStateSetModes(*mRootNode->getOrCreateStateSet(), osg::StateAttribute::ON); source->setStateSetModes(*mRootNode->getOrCreateStateSet(), osg::StateAttribute::ON);

@ -18,8 +18,6 @@
#include <osg/PolygonOffset> #include <osg/PolygonOffset>
#include <osg/observer_ptr> #include <osg/observer_ptr>
#include <OpenThreads/ReadWriteMutex>
#include <osgParticle/ParticleSystem> #include <osgParticle/ParticleSystem>
#include <osgParticle/ParticleSystemUpdater> #include <osgParticle/ParticleSystemUpdater>
#include <osgParticle/ModularEmitter> #include <osgParticle/ModularEmitter>
@ -27,6 +25,9 @@
#include <osgParticle/ConstantRateCounter> #include <osgParticle/ConstantRateCounter>
#include <osgParticle/RadialShooter> #include <osgParticle/RadialShooter>
#include <osgParticle/Operator>
#include <osgParticle/ModularProgram>
#include <components/misc/rng.hpp> #include <components/misc/rng.hpp>
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>
@ -1094,6 +1095,7 @@ private:
SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager) SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager)
: mSceneManager(sceneManager) : mSceneManager(sceneManager)
, mCamera(NULL)
, mAtmosphereNightRoll(0.f) , mAtmosphereNightRoll(0.f)
, mCreated(false) , mCreated(false)
, mIsStorm(false) , mIsStorm(false)
@ -1338,76 +1340,85 @@ protected:
osg::Uniform* mRainIntensityUniform; osg::Uniform* mRainIntensityUniform;
}; };
class WeatherParticleDrawCallback : public osg::Drawable::DrawCallback void SkyManager::setCamera(osg::Camera *camera)
{
mCamera = camera;
}
class WrapAroundOperator : public osgParticle::Operator
{ {
public: public:
WeatherParticleDrawCallback(osg::Vec3 &wrapRange) : osg::Drawable::DrawCallback() WrapAroundOperator(osg::Camera *camera, const osg::Vec3 &wrapRange): osgParticle::Operator()
{ {
mCamera = camera;
mWrapRange = wrapRange; mWrapRange = wrapRange;
mHalfWrapRange = mWrapRange / 2.0;
mPreviousCameraPosition = getCameraPosition();
} }
virtual void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable *drawable) const virtual osg::Object *cloneType() const override
{ {
return NULL;
}
osgParticle::ParticleSystem *ps = (osgParticle::ParticleSystem *) drawable; virtual osg::Object *clone(const osg::CopyOp &op) const override
{
osgParticle::ParticleSystem::ScopedReadLock *lock = new osgParticle::ParticleSystem::ScopedReadLock(*ps->getReadWriteMutex()); return NULL;
}
osg::Vec3 cameraPos = renderInfo.getCurrentCamera()->getInverseViewMatrix().getTrans();
osg::Vec3 cameraOffset = osg::Vec3( virtual void operate(osgParticle::Particle *P, double dt) override
fmod(cameraPos.x(), mWrapRange.x()), {
fmod(cameraPos.y(), mWrapRange.y()), }
fmod(cameraPos.z(), mWrapRange.z()));
std::vector<osg::Vec3> positionBackups; virtual void operateParticles(osgParticle::ParticleSystem *ps, double dt) override
{
osg::Vec3 position = getCameraPosition();
osg::Vec3 positionDifference = position - mPreviousCameraPosition;
osg::Matrix toWorld, toLocal; osg::Matrix toWorld, toLocal;
std::vector<osg::Matrix> worldMatrices = drawable->getWorldMatrices(); std::vector<osg::Matrix> worldMatrices = ps->getWorldMatrices();
if (!worldMatrices.empty()) if (!worldMatrices.empty())
{ {
toWorld = worldMatrices[0]; toWorld = worldMatrices[0];
toLocal.invert(toWorld); toLocal.invert(toWorld);
} }
for (int i = 0; i < ps->numParticles(); i++) for (int i = 0; i < ps->numParticles(); ++i)
{ {
osgParticle::Particle *particle = ps->getParticle(i); osgParticle::Particle *p = ps->getParticle(i);
positionBackups.push_back(particle->getPosition()); p->setPosition(toWorld.preMult(p->getPosition()));
particle->setPosition(toWorld.preMult(particle->getPosition())); p->setPosition(p->getPosition() - positionDifference);
particle->setPosition(particle->getPosition() - cameraOffset);
for (int j = 0; j < 3; j++) // wrap-around effect in all 3 directions for (int j = 0; j < 3; ++j) // wrap-around in all 3 dimensions
{ {
osg::Vec3 newPosition = particle->getPosition(); osg::Vec3 pos = p->getPosition();
if (particle->getPosition()[j] > mWrapRange[j] / 2.0) if (pos[j] < -mHalfWrapRange[j])
newPosition[j] -= mWrapRange[j]; pos[j] = mHalfWrapRange[j] + fmod(pos[j] - mHalfWrapRange[j],mWrapRange[j]);
else if (particle->getPosition()[j] < -mWrapRange[j] / 2.0) else if (pos[j] > mHalfWrapRange[j])
newPosition[j] += mWrapRange[j]; pos[j] = fmod(pos[j] + mHalfWrapRange[j],mWrapRange[j]) - mHalfWrapRange[j];
particle->setPosition(newPosition); p->setPosition(pos);
} }
particle->setPosition(toLocal.preMult(particle->getPosition())); p->setPosition(toLocal.preMult(p->getPosition()));
} }
delete lock; // unlock the mutex as ps will try to lock it in the following command mPreviousCameraPosition = position;
ps->drawImplementation(renderInfo);
lock = new osgParticle::ParticleSystem::ScopedReadLock(*ps->getReadWriteMutex());
for (int i = 0; i < ps->numParticles(); i++) // restore positions
ps->getParticle(i)->setPosition(positionBackups[i]);
delete lock;
} }
protected: protected:
osg::Camera *mCamera;
osg::Vec3 mPreviousCameraPosition;
osg::Vec3 mWrapRange; osg::Vec3 mWrapRange;
osg::Vec3 mHalfWrapRange;
osg::Vec3 getCameraPosition()
{
return mCamera->getInverseViewMatrix().getTrans();
}
}; };
void SkyManager::createRain() void SkyManager::createRain()
@ -1419,12 +1430,10 @@ void SkyManager::createRain()
mRainParticleSystem = new osgParticle::ParticleSystem; mRainParticleSystem = new osgParticle::ParticleSystem;
osg::Vec3 rainRange = osg::Vec3(600,600,600); osg::Vec3 rainRange = osg::Vec3(600,600,600);
mRainParticleSystem->setDrawCallback(new WeatherParticleDrawCallback(rainRange));
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));
mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,1)); mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,1));
mRainParticleSystem->setCullingActive(false);
osg::ref_ptr<osg::StateSet> stateset (mRainParticleSystem->getOrCreateStateSet()); osg::ref_ptr<osg::StateSet> stateset (mRainParticleSystem->getOrCreateStateSet());
@ -1463,6 +1472,11 @@ void SkyManager::createRain()
osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater (new osgParticle::ParticleSystemUpdater); osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater (new osgParticle::ParticleSystemUpdater);
updater->addParticleSystem(mRainParticleSystem); updater->addParticleSystem(mRainParticleSystem);
osg::ref_ptr<osgParticle::ModularProgram> program (new osgParticle::ModularProgram);
program->addOperator(new WrapAroundOperator(mCamera,rainRange));
program->setParticleSystem(mRainParticleSystem);
mRainNode->addChild(program);
mRainNode->addChild(emitter); mRainNode->addChild(emitter);
mRainNode->addChild(mRainParticleSystem); mRainNode->addChild(mRainParticleSystem);
mRainNode->addChild(updater); mRainNode->addChild(updater);
@ -1638,14 +1652,20 @@ void SkyManager::setWeather(const WeatherResult& weather)
SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor; SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor;
mParticleEffect->accept(disableFreezeOnCullVisitor); mParticleEffect->accept(disableFreezeOnCullVisitor);
SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem")); if (!weather.mIsStorm)
mParticleEffect->accept(findPSVisitor);
for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); i++)
{ {
osgParticle::ParticleSystem *ps = static_cast<osgParticle::ParticleSystem *>(findPSVisitor.mFoundNodes[i]); SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem"));
osg::Vec3 weatherRange = osg::Vec3(1024,1024,800); mParticleEffect->accept(findPSVisitor);
ps->setDrawCallback(new WeatherParticleDrawCallback(weatherRange));
for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); ++i)
{
osgParticle::ParticleSystem *ps = static_cast<osgParticle::ParticleSystem *>(findPSVisitor.mFoundNodes[i]);
osg::ref_ptr<osgParticle::ModularProgram> program (new osgParticle::ModularProgram);
program->addOperator(new WrapAroundOperator(mCamera,osg::Vec3(1024,1024,800)));
program->setParticleSystem(ps);
mParticleNode->addChild(program);
}
} }
} }
} }

@ -9,6 +9,11 @@
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include <osg/Vec4f> #include <osg/Vec4f>
namespace osg
{
class Camera;
}
namespace osg namespace osg
{ {
class Group; class Group;
@ -161,6 +166,8 @@ namespace MWRender
void listAssetsToPreload(std::vector<std::string>& models, std::vector<std::string>& textures); void listAssetsToPreload(std::vector<std::string>& models, std::vector<std::string>& textures);
void setCamera(osg::Camera *camera);
private: private:
void create(); void create();
///< no need to call this, automatically done on first enable() ///< no need to call this, automatically done on first enable()
@ -171,6 +178,8 @@ namespace MWRender
Resource::SceneManager* mSceneManager; Resource::SceneManager* mSceneManager;
osg::Camera* mCamera;
osg::ref_ptr<osg::Group> mRootNode; osg::ref_ptr<osg::Group> mRootNode;
osg::ref_ptr<osg::Group> mEarlyRenderBinRoot; osg::ref_ptr<osg::Group> mEarlyRenderBinRoot;

Loading…
Cancel
Save