Implemented seemless update of precipitation properties.

This commit is contained in:
Robert Osfield
2006-04-25 12:39:00 +00:00
parent 6558a5589f
commit 039457700d
3 changed files with 112 additions and 170 deletions

View File

@@ -31,71 +31,19 @@ class MyGustCallback : public osg::NodeCallback
osgParticle::PrecipitationEffect* pe = dynamic_cast<osgParticle::PrecipitationEffect*>(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());

View File

@@ -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<osg::Fog> _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<osg::Fog> _fog;
osg::ref_ptr<osg::Uniform> _inversePeriodUniform;
osg::ref_ptr<osg::Uniform> _particleSizeUniform;
osg::ref_ptr<osg::Uniform> _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<osg::StateSet> _precipitationStateSet;
osg::ref_ptr<osg::Geometry> _quadGeometry;
osg::ref_ptr<osg::StateSet> _quadStateSet;

View File

@@ -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<osgUtil::GLObjectsVisitor*>(&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<osgUtil::CullVisitor*>(&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()"<<std::endl;
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(_cellSize.z() / _particleSpeed);
@@ -316,19 +322,8 @@ void PrecipitationEffect::update()
osg::notify(osg::INFO)<<"Cell size X="<<length_u<<std::endl;
osg::notify(osg::INFO)<<"Cell size Y="<<length_v<<std::endl;
osg::notify(osg::INFO)<<"Cell size Z="<<length_w<<std::endl;
osg::BoundingBox& bb = _boundingBox;
if (bb.valid())
{
_origin.set(bb.xMin(), bb.yMin(), bb.zMin());
}
else
{
_origin.set(0.0f, 0.0f, 0.0f);
}
setUpGeometries((int)(_maximumParticleDensity * cellVolume));
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
_viewDrawableMap.clear();
@@ -336,23 +331,38 @@ void PrecipitationEffect::update()
// set up state/
{
_precipitationStateSet = new osg::StateSet;
if (!_stateset)
{
_stateset = new osg::StateSet;
_stateset->addUniform(new osg::Uniform("baseTexture",0));
osg::Uniform* inversePeriodUniform = new osg::Uniform("inversePeriod",1.0f/_period);
_stateset->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("<<numParticles<<")"<<std::endl;
bool needGeometryRebuild = false;
@@ -709,6 +717,15 @@ void PrecipitationEffect::cull(PrecipitationDrawableSet& pds, osgUtil::CullVisit
osg::Timer_t startTick = osg::Timer::instance()->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