diff --git a/examples/osgprecipitation/osgprecipitation.cpp b/examples/osgprecipitation/osgprecipitation.cpp index 9da55c8e9..6906eb28f 100644 --- a/examples/osgprecipitation/osgprecipitation.cpp +++ b/examples/osgprecipitation/osgprecipitation.cpp @@ -31,71 +31,19 @@ class MyGustCallback : public osg::NodeCallback osgParticle::PrecipitationEffect* pe = dynamic_cast(node); float value = sin(nv->getFrameStamp()->getReferenceTime()); - if (value<-0.5) pe->setWind(osg::Vec3(5.0f,0.0f,0.0f)); - else pe->setWind(osg::Vec3(1.0,0.0,0.0)); + if (value<-0.5) + { + pe->snow(1.0); + } + else + { + pe->rain(0.5); + } traverse(node, nv); } }; -#if 0 -osg::Node* createModel(osg::Node* loadedModel, osgParticle::PrecipitationParameters& parameters) -{ - osg::Group* group = new osg::Group; - - osg::BoundingBox bb(0.0, 0.0, 0.0, 100.0, 100.0, 100.0); - - if (loadedModel) - { - group->addChild(loadedModel); - - osg::BoundingSphere bs = loadedModel->getBound(); - - bb.set( -500, -500, 0, +500, +500, 10); - - parameters.boundingBox = bb; - - osg::StateSet* stateset = loadedModel->getOrCreateStateSet(); - - osg::Fog* fog = new osg::Fog; - - if (parameters.fogExponent<1.0) - { - fog->setMode(osg::Fog::LINEAR); - } - else if (parameters.fogExponent<2.0) - { - fog->setMode(osg::Fog::EXP); - } - else - { - fog->setMode(osg::Fog::EXP2); - } - - fog->setDensity(parameters.fogDensity); - fog->setStart(0.0f); - fog->setEnd(parameters.fogEnd); - fog->setColor(parameters.fogColour); - stateset->setAttributeAndModes(fog, osg::StateAttribute::ON); - - osg::LightSource* lightSource = new osg::LightSource; - group->addChild(lightSource); - - osg::Light* light = lightSource->getLight(); - light->setLightNum(0); - light->setPosition(osg::Vec4(0.0f,0.0f,1.0f,0.0f)); // directional light from above - light->setAmbient(osg::Vec4(0.8f,0.8f,0.8f,1.0f)); - light->setDiffuse(osg::Vec4(0.2f,0.2f,0.2f,1.0f)); - light->setSpecular(osg::Vec4(0.2f,0.2f,0.2f,1.0f)); - - - } - - group->addChild(createCellRainEffect(parameters)); - - return group; -} -#endif int main( int argc, char **argv ) { @@ -172,9 +120,6 @@ int main( int argc, char **argv ) viewer.setClearColor( precipitationEffect->getFog()->getColor() ); - // now force the effect to update all its internal state. - precipitationEffect->update(); - // if user request help write it out to cout. if (arguments.read("-h") || arguments.read("--help")) @@ -222,8 +167,6 @@ int main( int argc, char **argv ) light->setSpecular(osg::Vec4(0.2f,0.2f,0.2f,1.0f)); - - // set the scene to render viewer.setSceneData(group.get()); diff --git a/include/osgParticle/PrecipitationEffect b/include/osgParticle/PrecipitationEffect index ea890234c..023adccb1 100644 --- a/include/osgParticle/PrecipitationEffect +++ b/include/osgParticle/PrecipitationEffect @@ -25,7 +25,7 @@ namespace osgParticle { - class OSGPARTICLE_EXPORT PrecipitationEffect : public osg::Group + class OSGPARTICLE_EXPORT PrecipitationEffect : public osg::Node { public: @@ -45,12 +45,8 @@ namespace osgParticle /** Set all the parameters to create an snow effect of specified intensity.*/ void snow(float intensity); - - void setIntensity(float intensity) { _intensity = intensity; } - float getIntensity() const { return _intensity; } - - void setMaximumParticleDensity(float density) { _maximumParticleDensity = density; } + void setMaximumParticleDensity(float density) { if (_maximumParticleDensity==density) return; _maximumParticleDensity = density; _dirty = true;} float setMaximumParticleDensity() const { return _maximumParticleDensity; } void setWind(const osg::Vec3& wind) { _wind = wind; } @@ -59,16 +55,16 @@ namespace osgParticle void setPosition(const osg::Vec3& position) { _origin = position; } const osg::Vec3& getPosition() const { return _origin; } - void setCellSize(const osg::Vec3& cellSize) { _cellSize = cellSize; } + void setCellSize(const osg::Vec3& cellSize) { if (_cellSize==cellSize) return; _cellSize = cellSize; _dirty = true; } const osg::Vec3& getCellSize() const { return _cellSize; } - void setParticleSpeed(float particleSpeed) { _particleSpeed = particleSpeed; } + void setParticleSpeed(float particleSpeed) { if (_particleSpeed==particleSpeed) return; _particleSpeed = particleSpeed; _dirty = true; } float getParticleSpeed() const { return _particleSpeed; } - void setParticleSize(float particleSize) { _particleSize = particleSize; } + void setParticleSize(float particleSize) { if (_particleSize==particleSize) return; _particleSize = particleSize; _dirty = true;} float getParticleSize() const { return _particleSize; } - void setParticleColor(const osg::Vec4& color) { _particleColor = color; } + void setParticleColor(const osg::Vec4& color) { if (_particleColor==color) return; _particleColor = color; _dirty = true;} const osg::Vec4& getParticleColor() const { return _particleColor; } void setNearTransition(float nearTransition) { _nearTransition = nearTransition; } @@ -81,14 +77,19 @@ namespace osgParticle osg::Fog* getFog() { return _fog.get(); } const osg::Fog* getFog() const { return _fog.get(); } - void compileGLObjects(osg::State& state) const; + + osg::Geometry* getQuadGeometry() { return _quadGeometry.get(); } + osg::StateSet* getQuadStateSet() { return _quadStateSet.get(); } - void update(); protected: virtual ~PrecipitationEffect() {} + void compileGLObjects(osg::State& state) const; + + void update(); + void createGeometry(unsigned int numParticles, osg::Geometry* quad_geometry, osg::Geometry* line_geometry, @@ -116,6 +117,12 @@ namespace osgParticle void setGeometry(osg::Geometry* geom) { _geometry = geom; } osg::Geometry* getGeometry() { return _geometry.get(); } const osg::Geometry* getGeometry() const { return _geometry.get(); } + + void setDrawType(GLenum type) { _drawType = type; } + GLenum getDrawType() const { return _drawType; } + + void setNumberOfVertices(unsigned int numVertices) { _numberOfVertices = numVertices; } + unsigned int getNumberOfVertices() const { return _numberOfVertices; } virtual void drawImplementation(osg::State& state) const; @@ -182,6 +189,9 @@ namespace osgParticle mutable CellMatrixMap _currentCellMatrixMap; mutable CellMatrixMap _previousCellMatrixMap; + + GLenum _drawType; + unsigned int _numberOfVertices; }; @@ -196,18 +206,21 @@ namespace osgParticle bool build(const osg::Vec3 eyeLocal, int i, int j, int k, float startTime, PrecipitationDrawableSet& pds, osg::Polytope& frustum, osgUtil::CullVisitor* cv) const; // parameters - osg::BoundingBox _boundingBox; - float _intensity; - osg::Vec3 _wind; - float _particleSpeed; - float _particleSize; - osg::Vec4 _particleColor; - float _maximumParticleDensity; - osg::Vec3 _cellSize; - float _nearTransition; - float _farTransition; - bool _useFarLineSegments; - osg::ref_ptr _fog; + bool _dirty; + osg::Vec3 _wind; + float _particleSpeed; + float _particleSize; + osg::Vec4 _particleColor; + float _maximumParticleDensity; + osg::Vec3 _cellSize; + float _nearTransition; + float _farTransition; + bool _useFarLineSegments; + osg::ref_ptr _fog; + + osg::ref_ptr _inversePeriodUniform; + osg::ref_ptr _particleSizeUniform; + osg::ref_ptr _particleColorUniform; typedef std::pair< osg::NodeVisitor*, osg::NodePath > ViewIdenitifier; typedef std::map< ViewIdenitifier, PrecipitationDrawableSet > ViewDrawableMap; @@ -215,8 +228,6 @@ namespace osgParticle OpenThreads::Mutex _mutex; ViewDrawableMap _viewDrawableMap; - osg::ref_ptr _precipitationStateSet; - osg::ref_ptr _quadGeometry; osg::ref_ptr _quadStateSet; diff --git a/src/osgParticle/PrecipitationEffect.cpp b/src/osgParticle/PrecipitationEffect.cpp index 9e9c4846b..9342630c6 100644 --- a/src/osgParticle/PrecipitationEffect.cpp +++ b/src/osgParticle/PrecipitationEffect.cpp @@ -106,12 +106,14 @@ static osg::Image* createSpotLightImage(const osg::Vec4& centerColour, const osg PrecipitationEffect::PrecipitationEffect() { setNumChildrenRequiringUpdateTraversal(1); + + setUpGeometries(1024); + rain(0.5); } void PrecipitationEffect::rain(float intensity) { - _intensity = 1.0f; _wind.set(0.0f,0.0f,0.0f); _particleSpeed = -2.0f + -5.0f*intensity; _particleSize = 0.01 + 0.02*intensity; @@ -129,12 +131,13 @@ void PrecipitationEffect::rain(float intensity) _useFarLineSegments = false; + _dirty = true; + update(); } void PrecipitationEffect::snow(float intensity) { - _intensity = 1.0f; _wind.set(0.0f,0.0f,0.0f); _particleSpeed = -0.75f - 0.25f*intensity; _particleSize = 0.02f + 0.03f*intensity; @@ -152,13 +155,16 @@ void PrecipitationEffect::snow(float intensity) _useFarLineSegments = false; + _dirty = true; + update(); } PrecipitationEffect::PrecipitationEffect(const PrecipitationEffect& copy, const osg::CopyOp& copyop): - osg::Group(copy,copyop) + osg::Node(copy,copyop) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1); + _dirty = true; update(); } @@ -188,6 +194,8 @@ void PrecipitationEffect::traverse(osg::NodeVisitor& nv) { if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) { + if (_dirty) update(); + if (nv.getFrameStamp()) { double currentTime = nv.getFrameStamp()->getReferenceTime(); @@ -197,12 +205,13 @@ void PrecipitationEffect::traverse(osg::NodeVisitor& nv) previousTime = currentTime; } - Group::traverse(nv); return; } if (nv.getVisitorType() == osg::NodeVisitor::NODE_VISITOR) { + if (_dirty) update(); + osgUtil::GLObjectsVisitor* globjVisitor = dynamic_cast(&nv); if (globjVisitor) { @@ -212,21 +221,18 @@ void PrecipitationEffect::traverse(osg::NodeVisitor& nv) } } - Group::traverse(nv); return; } if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR) { - Group::traverse(nv); return; } osgUtil::CullVisitor* cv = dynamic_cast(&nv); if (!cv) { - Group::traverse(nv); return; } @@ -246,21 +252,24 @@ void PrecipitationEffect::traverse(osg::NodeVisitor& nv) precipitationDrawableSet->_quadPrecipitationDrawable->setRequiresPreviousMatrix(true); precipitationDrawableSet->_quadPrecipitationDrawable->setGeometry(_quadGeometry.get()); precipitationDrawableSet->_quadPrecipitationDrawable->setStateSet(_quadStateSet.get()); - + precipitationDrawableSet->_quadPrecipitationDrawable->setDrawType(GL_QUADS); + precipitationDrawableSet->_linePrecipitationDrawable = new PrecipitationDrawable; precipitationDrawableSet->_linePrecipitationDrawable->setRequiresPreviousMatrix(true); precipitationDrawableSet->_linePrecipitationDrawable->setGeometry(_lineGeometry.get()); precipitationDrawableSet->_linePrecipitationDrawable->setStateSet(_lineStateSet.get()); + precipitationDrawableSet->_linePrecipitationDrawable->setDrawType(GL_LINES); precipitationDrawableSet->_pointPrecipitationDrawable = new PrecipitationDrawable; precipitationDrawableSet->_pointPrecipitationDrawable->setRequiresPreviousMatrix(false); precipitationDrawableSet->_pointPrecipitationDrawable->setGeometry(_pointGeometry.get()); precipitationDrawableSet->_pointPrecipitationDrawable->setStateSet(_pointStateSet.get()); + precipitationDrawableSet->_pointPrecipitationDrawable->setDrawType(GL_POINTS); } cull(*precipitationDrawableSet, cv); - cv->pushStateSet(_precipitationStateSet.get()); + cv->pushStateSet(_stateset.get()); float depth = 0.0f; if (!precipitationDrawableSet->_quadPrecipitationDrawable->getCurrentCellMatrixMap().empty()) @@ -287,20 +296,17 @@ void PrecipitationEffect::traverse(osg::NodeVisitor& nv) cv->popStateSet(); } - - Group::traverse(nv); } void PrecipitationEffect::update() { + _dirty = false; + osg::notify(osg::INFO)<<"PrecipitationEffect::update()"<setMode(GL_LIGHTING, osg::StateAttribute::OFF); + _stateset->setMode(GL_BLEND, osg::StateAttribute::ON); - _precipitationStateSet->addUniform(inversePeriodUniform); // float + osg::Texture2D* texture = new osg::Texture2D(createSpotLightImage(osg::Vec4(1.0f,1.0f,1.0f,1.0f),osg::Vec4(1.0f,1.0f,1.0f,0.0f),32,1.0)); + _stateset->setTextureAttribute(0, texture); + } - _precipitationStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); - _precipitationStateSet->setMode(GL_BLEND, osg::StateAttribute::ON); + if (!_inversePeriodUniform) + { + _inversePeriodUniform = new osg::Uniform("inversePeriod",1.0f/_period); + _stateset->addUniform(_inversePeriodUniform.get()); + } + else _inversePeriodUniform->set(1.0f/_period); - osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0); - _precipitationStateSet->addUniform(baseTextureSampler); - - osg::Texture2D* texture = new osg::Texture2D(createSpotLightImage(osg::Vec4(1.0f,1.0f,1.0f,1.0f),osg::Vec4(1.0f,1.0f,1.0f,0.0f),32,1.0)); - _precipitationStateSet->setTextureAttribute(0, texture); - - _precipitationStateSet->addUniform(new osg::Uniform("particleColour", _particleColor)); - _precipitationStateSet->addUniform(new osg::Uniform("particleSize", _particleSize)); + if (!_particleSizeUniform) + { + _particleColorUniform = new osg::Uniform("particleColour", _particleColor); + _stateset->addUniform(_particleColorUniform.get()); + } + else _particleColorUniform->set(_particleColor); + + if (!_particleSizeUniform) + { + _particleSizeUniform = new osg::Uniform("particleSize", _particleSize); + _stateset->addUniform(_particleSizeUniform.get()); + } + else _particleSizeUniform->set(_particleSize); } @@ -387,7 +397,6 @@ void PrecipitationEffect::createGeometry(unsigned int numParticles, quad_geometry->setVertexArray(quad_vertices); quad_geometry->setTexCoordArray(0, quad_offsets); - quad_geometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, numParticles*4)); } // configure line_geometry; @@ -402,7 +411,6 @@ void PrecipitationEffect::createGeometry(unsigned int numParticles, line_geometry->setVertexArray(line_vertices); line_geometry->setTexCoordArray(0, line_offsets); - line_geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, numParticles*2)); } // configure point_geometry; @@ -417,7 +425,6 @@ void PrecipitationEffect::createGeometry(unsigned int numParticles, point_geometry->setVertexArray(point_vertices); point_geometry->setTexCoordArray(0, point_offsets); - point_geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, numParticles)); } // set up vertex attribute data. @@ -462,6 +469,7 @@ void PrecipitationEffect::setUpGeometries(unsigned int numParticles) unsigned int lineRenderBin = 12; unsigned int pointRenderBin = 11; + osg::notify(osg::INFO)<<"PrecipitationEffect::setUpGeometries("<tick(); #endif + float cellVolume = _cellSize.x() * _cellSize.y() * _cellSize.z(); + int numberOfParticles = (int)(_maximumParticleDensity * cellVolume); + + if (numberOfParticles==0) return; + + pds._quadPrecipitationDrawable->setNumberOfVertices(numberOfParticles*4); + pds._linePrecipitationDrawable->setNumberOfVertices(numberOfParticles*2); + pds._pointPrecipitationDrawable->setNumberOfVertices(numberOfParticles); + pds._quadPrecipitationDrawable->newFrame(); pds._linePrecipitationDrawable->newFrame(); pds._pointPrecipitationDrawable->newFrame(); @@ -836,7 +853,9 @@ bool PrecipitationEffect::build(const osg::Vec3 eyeLocal, int i, int j, int k, f //////////////////////////////////////////////////////////////////////////////////////////////////// PrecipitationEffect::PrecipitationDrawable::PrecipitationDrawable(): - _requiresPreviousMatrix(true) + _requiresPreviousMatrix(true), + _drawType(GL_QUADS), + _numberOfVertices(0) { setSupportsDisplayList(false); } @@ -844,7 +863,9 @@ PrecipitationEffect::PrecipitationDrawable::PrecipitationDrawable(): PrecipitationEffect::PrecipitationDrawable::PrecipitationDrawable(const PrecipitationDrawable& copy, const osg::CopyOp& copyop): Drawable(copy,copyop), _requiresPreviousMatrix(copy._requiresPreviousMatrix), - _geometry(copy._geometry) + _geometry(copy._geometry), + _drawType(copy._drawType), + _numberOfVertices(copy._numberOfVertices) { } @@ -912,41 +933,8 @@ void PrecipitationEffect::PrecipitationDrawable::drawImplementation(osg::State& _geometry->draw(state); - } - - for(CellMatrixMap::const_iterator itr = _currentCellMatrixMap.begin(); - itr != _currentCellMatrixMap.end(); - ++itr) - { - extensions->glMultiTexCoord1f(GL_TEXTURE0+1, itr->second.startTime); - - // load cells current modelview matrix - if (_requiresPreviousMatrix) - { - glMatrixMode( GL_MODELVIEW ); - glLoadMatrix(itr->second.modelview.ptr()); - - CellMatrixMap::const_iterator pitr = _previousCellMatrixMap.find(itr->first); - if (pitr != _previousCellMatrixMap.end()) - { - // load previous frame modelview matrix for motion blurr effect - glMatrixMode( GL_TEXTURE ); - glLoadMatrix(pitr->second.modelview.ptr()); - } - else - { - // use current modelview matrix as "previous" frame value, cancelling motion blurr effect - glMatrixMode( GL_TEXTURE ); - glLoadMatrix(itr->second.modelview.ptr()); - } - } - else - { - glLoadMatrix(itr->second.modelview.ptr()); - } - - _geometry->draw(state); - + unsigned int numVertices = osg::minimum(_geometry->getVertexArray()->getNumElements(), _numberOfVertices); + glDrawArrays(_drawType, 0, numVertices); } // restore OpenGL matrices