diff --git a/examples/osgprecipitation/osgprecipitation.cpp b/examples/osgprecipitation/osgprecipitation.cpp index e318d2176..9da55c8e9 100644 --- a/examples/osgprecipitation/osgprecipitation.cpp +++ b/examples/osgprecipitation/osgprecipitation.cpp @@ -31,8 +31,8 @@ class MyGustCallback : public osg::NodeCallback osgParticle::PrecipitationEffect* pe = dynamic_cast(node); float value = sin(nv->getFrameStamp()->getReferenceTime()); - if (value<-0.5) pe->getParameters()->wind.set(5.0,0.0,0.0); - else pe->getParameters()->wind.set(1.0,0.0,0.0); + 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)); traverse(node, nv); } @@ -130,49 +130,47 @@ int main( int argc, char **argv ) viewer.getUsage(*arguments.getApplicationUsage()); osg::ref_ptr precipitationEffect = new osgParticle::PrecipitationEffect; - osgParticle::PrecipitationParameters& parameters = *precipitationEffect->getParameters(); float intensity; - while (arguments.read("--snow", intensity)) parameters.snow(intensity); - while (arguments.read("--rain", intensity)) parameters.rain(intensity); + while (arguments.read("--snow", intensity)) precipitationEffect->snow(intensity); + while (arguments.read("--rain", intensity)) precipitationEffect->rain(intensity); - while (arguments.read("--particleSize", parameters.particleSize)) {} - while (arguments.read("--particleColor", parameters.particleColour.r(), parameters.particleColour.g(), parameters.particleColour.b(), parameters.particleColour.a())) {} - while (arguments.read("--particleColour", parameters.particleColour.r(), parameters.particleColour.g(), parameters.particleColour.b(), parameters.particleColour.a())) {} + float value; + while (arguments.read("--particleSize", value)) precipitationEffect->setParticleSize(value); + + osg::Vec4 color; + while (arguments.read("--particleColor", color.r(), color.g(), color.b(), color.a())) precipitationEffect->setParticleColor(color); + while (arguments.read("--particleColour", color.r(), color.g(), color.b(), color.a())) precipitationEffect->setParticleColor(color); osg::Vec3 wind; - while (arguments.read("--wind", wind.x(), wind.y(), wind.z())) parameters.wind = wind; + while (arguments.read("--wind", wind.x(), wind.y(), wind.z())) precipitationEffect->setWind(wind); - while (arguments.read("--particleVelocity", parameters.particleVelocity)) {} + while (arguments.read("--particleSpeed", value)) precipitationEffect->setParticleSpeed(value); - while (arguments.read("--nearTransition", parameters.nearTransition )) {} - while (arguments.read("--farTransition", parameters.farTransition )) {} + while (arguments.read("--nearTransition", value )) precipitationEffect->setNearTransition(value); + while (arguments.read("--farTransition", value )) precipitationEffect->setFarTransition(value); - while (arguments.read("--particleDensity", parameters.particleDensity )) {} + while (arguments.read("--particleDensity", value )) precipitationEffect->setMaximumParticleDensity(value); - while (arguments.read("--cellSizeX", parameters.cellSizeX )) {} - while (arguments.read("--cellSizeY", parameters.cellSizeY )) {} - while (arguments.read("--cellSizeZ", parameters.cellSizeZ )) {} + osg::Vec3 cellSize; + while (arguments.read("--cellSize", cellSize.x(), cellSize.y(), cellSize.z())) precipitationEffect->setCellSize(cellSize); - while (arguments.read("--boundingBox", parameters.boundingBox.xMin(), - parameters.boundingBox.yMin(), - parameters.boundingBox.zMin(), - parameters.boundingBox.xMax(), - parameters.boundingBox.yMax(), - parameters.boundingBox.zMax())) {} + osg::BoundingBox bb; + while (arguments.read("--boundingBox", bb.xMin(), + bb.yMin(), + bb.zMin(), + bb.xMax(), + bb.yMax(), + bb.zMax())) {} - while (arguments.read("--fogDensity", parameters.fogDensity )) {} - while (arguments.read("--fogExponent", parameters.fogExponent )) {} - while (arguments.read("--fogEnd", parameters.fogEnd )) {} - while (arguments.read("--fogColor", parameters.fogColour.r(), parameters.fogColour.g(), parameters.fogColour.b(), parameters.fogColour.a())) {} - while (arguments.read("--fogColour", parameters.fogColour.r(), parameters.fogColour.g(), parameters.fogColour.b(), parameters.fogColour.a())) {} + while (arguments.read("--fogDensity", value )) precipitationEffect->getFog()->setDensity(value); + while (arguments.read("--fogColor", color.r(), color.g(), color.b(), color.a() )) precipitationEffect->getFog()->setColor(color); + while (arguments.read("--fogColour", color.r(), color.g(), color.b(), color.a() )) precipitationEffect->getFog()->setColor(color); - while (arguments.read("--useFarLineSegments")) { parameters.useFarLineSegments = true; } +// while (arguments.read("--useFarLineSegments")) { parameters.useFarLineSegments = true; } - - - viewer.setClearColor(parameters.clearColour); + viewer.setClearColor( precipitationEffect->getFog()->getColor() ); // now force the effect to update all its internal state. precipitationEffect->update(); @@ -204,11 +202,28 @@ int main( int argc, char **argv ) } // precipitationEffect->setUpdateCallback(new MyGustCallback); + osg::ref_ptr group = new osg::Group; group->addChild(precipitationEffect.get()); + group->addChild(loadedModel.get()); + loadedModel->getOrCreateStateSet()->setAttributeAndModes(precipitationEffect->getFog()); + // create the light + 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)); + + + + // set the scene to render viewer.setSceneData(group.get()); diff --git a/include/osgParticle/PrecipitationEffect b/include/osgParticle/PrecipitationEffect index a875c8b5b..cbd27f419 100644 --- a/include/osgParticle/PrecipitationEffect +++ b/include/osgParticle/PrecipitationEffect @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -26,33 +25,6 @@ namespace osgParticle { - struct OSGPARTICLE_EXPORT PrecipitationParameters : public osg::Referenced - { - PrecipitationParameters(); - - void rain (float intensity); - - void snow(float intensity); - - osg::Vec3 wind; - osg::BoundingBox boundingBox; - float particleVelocity; - float particleSize; - osg::Vec4 particleColour; - float particleDensity; - float cellSizeX; - float cellSizeY; - float cellSizeZ; - float nearTransition; - float farTransition; - float fogExponent; - float fogDensity; - float fogEnd; - osg::Vec4 fogColour; - osg::Vec4 clearColour; - bool useFarLineSegments; - }; - class OSGPARTICLE_EXPORT PrecipitationEffect : public osg::Group { public: @@ -66,12 +38,48 @@ namespace osgParticle virtual void accept(osg::NodeVisitor& nv) { if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); } } virtual void traverse(osg::NodeVisitor& nv); + + + /** Set all the parameters to create an rain effect of specified intensity.*/ + void rain(float intensity); + + /** Set all the parameters to create an rain effect of specified intensity.*/ + void snow(float intensity); - void setParameters(PrecipitationParameters* parameters); - PrecipitationParameters* getParameters() { return _parameters.get(); } + void setIntensity(float intensity) { _intensity = intensity; } + float getIntensity() const { return _intensity; } - const PrecipitationParameters* getParameters() const { return _parameters.get(); } + void setMaximumParticleDensity(float density) { _maximumParticleDensity = density; } + float setMaximumParticleDensity() const { return _maximumParticleDensity; } + + void setWind(const osg::Vec3& wind) { _wind = wind; } + const osg::Vec3& getWind() const { return _wind; } + + void setPosition(const osg::Vec3& position) { _origin = position; } + const osg::Vec3& getPosition() const { return _origin; } + + void setCellSize(const osg::Vec3& cellSize) { _cellSize = cellSize; } + const osg::Vec3& getCellSize() const { return _cellSize; } + + void setParticleSpeed(float particleSpeed) { _particleSpeed = particleSpeed; } + float getParticleSpeed() const { return _particleSpeed; } + + void setParticleSize(float particleSize) { _particleSize = particleSize; } + float getParticleSize() const { return _particleSize; } + + void setParticleColor(const osg::Vec4& color) { _particleColor = color; } + const osg::Vec4& getParticleColor() const { return _particleColor; } + + void setNearTransition(float nearTransition) { _nearTransition = nearTransition; } + float getNearTransition() const { return _nearTransition; } + + void setFarTransition(float farTransition) { _farTransition = farTransition; } + float getFarTransition() const { return _farTransition; } + + void setFog(osg::Fog* fog) { _fog = fog; } + osg::Fog* getFog() { return _fog.get(); } + const osg::Fog* getFog() const { return _fog.get(); } void compileGLObjects(osg::State& state) const; @@ -116,17 +124,6 @@ namespace osgParticle Cell(int in_i, int in_j, int in_k): i(in_i), j(in_j), k(in_k) {} - - inline bool operator == (const Cell& rhs) const - { - return i==rhs.i && j==rhs.j && k==rhs.k; - } - - inline bool operator != (const Cell& rhs) const - { - return i!=rhs.i || j!=rhs.j || k!=rhs.k; - } - inline bool operator < (const Cell& rhs) const { if (i MatrixStartTimePair; - - typedef std::map< Cell, MatrixStartTimePair > CellMatrixMap; + typedef std::map< Cell, DepthMatrixStartTime > CellMatrixMap; CellMatrixMap& getCurrentCellMatrixMap() { return _currentCellMatrixMap; } CellMatrixMap& getPreviousCellMatrixMap() { return _previousCellMatrixMap; } @@ -179,12 +186,19 @@ namespace osgParticle void cull(PrecipitationDrawableSet& pds, osgUtil::CullVisitor* cv) const; bool build(const osg::Vec3 eyeLocal, int i, int j, int k, float startTime, PrecipitationDrawableSet& pds, osg::Polytope& frustum, osgUtil::CullVisitor* cv) const; - osg::ref_ptr _parameters; - - // elements for the subgraph - osg::ref_ptr _clearNode; - osg::ref_ptr _fog; - + // 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; typedef std::pair< osg::NodeVisitor*, osg::NodePath > ViewIdenitifier; typedef std::map< ViewIdenitifier, PrecipitationDrawableSet > ViewDrawableMap; @@ -203,7 +217,7 @@ namespace osgParticle osg::ref_ptr _pointGeometry; osg::ref_ptr _pointStateSet; - + // cache variables. float _period; osg::Vec3 _origin; osg::Vec3 _du; diff --git a/src/osgParticle/PrecipitationEffect.cpp b/src/osgParticle/PrecipitationEffect.cpp index c8fd774dc..adffaa4c1 100644 --- a/src/osgParticle/PrecipitationEffect.cpp +++ b/src/osgParticle/PrecipitationEffect.cpp @@ -1,4 +1,4 @@ -/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -103,56 +103,55 @@ static osg::Image* createSpotLightImage(const osg::Vec4& centerColour, const osg } -PrecipitationParameters::PrecipitationParameters() -{ - rain(0.5); -} - -void PrecipitationParameters::rain(float intensity) -{ - wind.set(0.0f,0.0f,0.0f); - particleVelocity = -2.0f + -5.0f*intensity; - particleSize = 0.01 + 0.02*intensity; - particleColour = osg::Vec4(0.6, 0.6, 0.6, 1.0) - osg::Vec4(0.1, 0.1, 0.1, 1.0)* intensity; - particleDensity = intensity * 8.5f; - cellSizeX = 5.0f / (0.25f+intensity); - cellSizeY = 5.0f / (0.25f+intensity); - cellSizeZ = 5.0f; - nearTransition = 25.f; - farTransition = 100.0f - 60.0f*sqrtf(intensity); - fogExponent = 1.0f; - fogDensity = 0.005f*intensity; - fogEnd = 250/(0.01 + intensity); - fogColour.set(0.5, 0.5, 0.5, 1.0); - clearColour.set(0.5, 0.5, 0.5, 1.0); - useFarLineSegments = false; -} - -void PrecipitationParameters::snow(float intensity) -{ - wind.set(0.0f,0.0f,0.0f); - particleVelocity = -0.75f - 0.25f*intensity; - particleSize = 0.02f + 0.03f*intensity; - particleColour = osg::Vec4(0.85f, 0.85f, 0.85f, 1.0f) - osg::Vec4(0.1f, 0.1f, 0.1f, 1.0f)* intensity; - particleDensity = intensity * 8.2f; - cellSizeX = 5.0f / (0.25f+intensity); - cellSizeY = 5.0f / (0.25f+intensity); - cellSizeZ = 5.0f; - nearTransition = 25.0f; - farTransition = 100.0f - 60.0f*sqrtf(intensity); - fogExponent = 1.0f; - fogDensity = 0.02f*intensity; - fogEnd = 150.0f/(0.01f + intensity); - fogColour.set(0.6, 0.6, 0.6, 1.0); - clearColour.set(0.6, 0.6, 0.6, 1.0); - useFarLineSegments = false; -} - - PrecipitationEffect::PrecipitationEffect() { setNumChildrenRequiringUpdateTraversal(1); - setParameters(new PrecipitationParameters); + 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; + _particleColor = osg::Vec4(0.6, 0.6, 0.6, 1.0) - osg::Vec4(0.1, 0.1, 0.1, 1.0)* intensity; + _maximumParticleDensity = intensity * 8.5f; + _cellSize.set(5.0f / (0.25f+intensity), 5.0f / (0.25f+intensity), 5.0f); + _nearTransition = 25.f; + _farTransition = 100.0f - 60.0f*sqrtf(intensity); + + if (!_fog) _fog = new osg::Fog; + + _fog->setMode(osg::Fog::EXP); + _fog->setDensity(0.005f*intensity); + _fog->setColor(osg::Vec4(0.5, 0.5, 0.5, 1.0)); + + _useFarLineSegments = false; + + 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; + _particleColor = osg::Vec4(0.85f, 0.85f, 0.85f, 1.0f) - osg::Vec4(0.1f, 0.1f, 0.1f, 1.0f)* intensity; + _maximumParticleDensity = intensity * 8.2f; + _cellSize.set(5.0f / (0.25f+intensity), 5.0f / (0.25f+intensity), 5.0f); + _nearTransition = 25.f; + _farTransition = 100.0f - 60.0f*sqrtf(intensity); + + if (!_fog) _fog = new osg::Fog; + + _fog->setMode(osg::Fog::EXP); + _fog->setDensity(0.01f*intensity); + _fog->setColor(osg::Vec4(0.6, 0.6, 0.6, 1.0)); + + _useFarLineSegments = false; + update(); } @@ -160,7 +159,6 @@ PrecipitationEffect::PrecipitationEffect(const PrecipitationEffect& copy, const osg::Group(copy,copyop) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1); - setParameters(const_cast(copy._parameters.get())); update(); } @@ -195,7 +193,7 @@ void PrecipitationEffect::traverse(osg::NodeVisitor& nv) double currentTime = nv.getFrameStamp()->getReferenceTime(); static double previousTime = currentTime; double delta = currentTime - previousTime; - _origin += _parameters->wind * delta; + _origin += _wind * delta; previousTime = currentTime; } @@ -221,7 +219,6 @@ void PrecipitationEffect::traverse(osg::NodeVisitor& nv) if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR) { - osg::notify(osg::NOTICE)<<"!CUll"<(&nv); if (!cv) { - osg::notify(osg::NOTICE)<<"Cull cast failed"<_quadPrecipitationDrawable) { - osg::notify(osg::NOTICE)<<"Setting up"<_quadPrecipitationDrawable = new PrecipitationDrawable; precipitationDrawableSet->_quadPrecipitationDrawable->setRequiresPreviousMatrix(true); precipitationDrawableSet->_quadPrecipitationDrawable->setGeometry(_quadGeometry.get()); @@ -297,55 +291,19 @@ void PrecipitationEffect::traverse(osg::NodeVisitor& nv) Group::traverse(nv); } -void PrecipitationEffect::setParameters(PrecipitationParameters* parameters) -{ - if (_parameters==parameters) return; - - _parameters = parameters; -} - void PrecipitationEffect::update() { - osg::notify(osg::NOTICE)<<"PrecipitationEffect::update()"<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); - } - - if (_clearNode.valid()) - { - _clearNode->setClearColor(_parameters->clearColour); - } - - - float length_u = _parameters->cellSizeX; - float length_v = _parameters->cellSizeY; - float length_w = _parameters->cellSizeZ; + float length_u = _cellSize.x(); + float length_v = _cellSize.y(); + float length_w = _cellSize.z(); // volume of a single cell float cellVolume = length_u*length_v*length_w; // time taken to get from start to the end of cycle - _period = fabsf(_parameters->cellSizeZ / _parameters->particleVelocity); + _period = fabsf(_cellSize.z() / _particleSpeed); _du.set(length_u, 0.0f, 0.0f); _dv.set(0.0f, length_v, 0.0f); @@ -355,12 +313,11 @@ void PrecipitationEffect::update() _inverse_dv.set(0.0f, 1.0f/length_v, 0.0f); _inverse_dw.set(0.0f, 0.0f, 1.0f/length_w); - osg::notify(osg::NOTICE)<<"Cell size X="<particleColour)); - _precipitationStateSet->addUniform(new osg::Uniform("particleSize", _parameters->particleSize)); + _precipitationStateSet->addUniform(new osg::Uniform("particleColour", _particleColor)); + _precipitationStateSet->addUniform(new osg::Uniform("particleSize", _particleSize)); } @@ -505,12 +462,39 @@ void PrecipitationEffect::setUpGeometries(unsigned int numParticles) unsigned int lineRenderBin = 12; unsigned int pointRenderBin = 11; - osg::notify(osg::NOTICE)<<"setUpGeometries("<getVertexArray()->getNumElements() != 4*numParticles) { _quadGeometry = new osg::Geometry; _quadGeometry->setUseVertexBufferObjects(true); + needGeometryRebuild = true; + } + if (!_lineGeometry || _lineGeometry->getVertexArray()->getNumElements() != 2*numParticles) + { + _lineGeometry = new osg::Geometry; + _lineGeometry->setUseVertexBufferObjects(true); + needGeometryRebuild = true; + } + + if (!_pointGeometry || _pointGeometry->getVertexArray()->getNumElements() != numParticles) + { + _pointGeometry = new osg::Geometry; + _pointGeometry->setUseVertexBufferObjects(true); + needGeometryRebuild = true; + } + + if (needGeometryRebuild) + { + createGeometry(numParticles, _quadGeometry.get(), _lineGeometry.get(), _pointGeometry.get()); + } + + + if (!_quadStateSet) + { _quadStateSet = new osg::StateSet; osg::Program* program = new osg::Program; @@ -583,10 +567,8 @@ void PrecipitationEffect::setUpGeometries(unsigned int numParticles) } + if (!_lineStateSet) { - _lineGeometry = new osg::Geometry; - _lineGeometry->setUseVertexBufferObjects(true); - _lineStateSet = new osg::StateSet; osg::Program* program = new osg::Program; @@ -656,10 +638,8 @@ void PrecipitationEffect::setUpGeometries(unsigned int numParticles) } + if (!_pointStateSet) { - _pointGeometry = new osg::Geometry; - _pointGeometry->setUseVertexBufferObjects(true); - _pointStateSet = new osg::StateSet; osg::Program* program = new osg::Program; @@ -720,7 +700,6 @@ void PrecipitationEffect::setUpGeometries(unsigned int numParticles) _pointStateSet->setRenderBinDetails(pointRenderBin,"DepthSortedBin"); } - createGeometry(numParticles, _quadGeometry.get(), _lineGeometry.get(), _pointGeometry.get()); } @@ -753,9 +732,9 @@ void PrecipitationEffect::cull(PrecipitationDrawableSet& pds, osgUtil::CullVisit frustum.transformProvidingInverse(cv->getProjectionMatrix()); frustum.transformProvidingInverse(cv->getModelViewMatrix()); - float i_delta = _parameters->farTransition * _inverse_du.x(); - float j_delta = _parameters->farTransition * _inverse_dv.y(); - float k_delta = 1;//_parameters->nearTransition * _inverse_dw.z(); + float i_delta = _farTransition * _inverse_du.x(); + float j_delta = _farTransition * _inverse_dv.y(); + float k_delta = 1;//_nearTransition * _inverse_dw.z(); int i_min = (int)floor(eye_i - i_delta); int j_min = (int)floor(eye_j - j_delta); @@ -811,16 +790,16 @@ bool PrecipitationEffect::build(const osg::Vec3 eyeLocal, int i, int j, int k, f float distance = (center-eyeLocal).length(); osg::Matrix* mymodelview = 0; - if (distance < _parameters->nearTransition) + if (distance < _nearTransition) { PrecipitationDrawable::DepthMatrixStartTime& mstp = pds._quadPrecipitationDrawable->getCurrentCellMatrixMap()[PrecipitationDrawable::Cell(i,k,j)]; mstp.depth = distance; mstp.startTime = startTime; mymodelview = &mstp.modelview; } - else if (distance <= _parameters->farTransition) + else if (distance <= _farTransition) { - if (_parameters->useFarLineSegments) + if (_useFarLineSegments) { PrecipitationDrawable::DepthMatrixStartTime& mstp = pds._linePrecipitationDrawable->getCurrentCellMatrixMap()[PrecipitationDrawable::Cell(i,k,j)]; mstp.depth = distance;