From 264ae127706f1de831135669275cdd8aecde8f63 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 13 Apr 2006 19:05:26 +0000 Subject: [PATCH] Added command line options and various speed improvements. --- .../osgprecipitation/osgprecipitation.cpp | 202 +++++++++++++++--- examples/osgprecipitation/point_rain.vert | 8 +- examples/osgprecipitation/quad_rain.vert | 4 +- 3 files changed, 183 insertions(+), 31 deletions(-) diff --git a/examples/osgprecipitation/osgprecipitation.cpp b/examples/osgprecipitation/osgprecipitation.cpp index ccd7f7299..7db7f76d8 100644 --- a/examples/osgprecipitation/osgprecipitation.cpp +++ b/examples/osgprecipitation/osgprecipitation.cpp @@ -27,6 +27,92 @@ float random(float min,float max) { return min + (max-min)*(float)rand()/(float)RAND_MAX; } +struct PrecipatationParameters : public osg::Referenced +{ + PrecipatationParameters(): + particleVelocity(0.0,0.0,-5.0), + particleSize(0.02), + particleColour(0.6, 0.6, 0.6, 1.0), + numberOfParticles(10000000), + numberOfCellsX(100), + numberOfCellsY(100), + numberOfCellsZ(1), + nearTransition(25.0), + farTransition(100.0) + {} + + void rain (float intensity) + { + particleVelocity = osg::Vec3(0.0,0.0,-2.0) + osg::Vec3(0.0,0.0,-10.0)*intensity; + particleSize = 0.01 + 0.04*intensity; + numberOfParticles = intensity * 100000000; + particleColour = osg::Vec4(0.6, 0.6, 0.6, 1.0); + } + + void snow(float intensity) + { + particleVelocity = osg::Vec3(0.0,0.0,-1.0) + osg::Vec3(0.0,0.0,-0.5)*intensity; + particleSize = 0.02 + 0.05*intensity; + numberOfParticles = intensity * 100000000; + particleColour = osg::Vec4(0.8, 0.8, 0.8, 1.0); + } + + osg::BoundingBox boundingBox; + osg::Vec3 particleVelocity; + float particleSize; + osg::Vec4 particleColour; + unsigned int numberOfParticles; + unsigned int numberOfCellsX; + unsigned int numberOfCellsY; + unsigned int numberOfCellsZ; + float nearTransition; + float farTransition; +}; + +struct PrecipitationCullCallback : public virtual osg::Drawable::CullCallback +{ + PrecipitationCullCallback() {} + + PrecipitationCullCallback(const PrecipitationCullCallback&,const osg::CopyOp&) {} + + META_Object(osg,PrecipitationCullCallback); + + /** do customized cull code, return true if drawable should be culled.*/ + virtual bool cull(osg::NodeVisitor* nodeVisitor, osg::Drawable* drawable, osg::State* state) const + { + osgUtil::CullVisitor* cv = dynamic_cast(nodeVisitor); + if (cv) + { + float distance = nodeVisitor->getDistanceFromEyePoint(drawable->getBound().center(),true); + +// if (distance<-4.0) return true; + +#if 0 + + const osg::BoundingBox& bb = drawable->getBound(); + const osg::Polytope& frustum = cv->getCurrentCullingSet().getFrustum(); + int numPointsInside = 0; + for(unsigned int i=0; i<8; ++i) + { + if (frustum.contains(bb.corner(i))) ++numPointsInside; + } + + std::cout<<" "<getName()<<" distance "<getName()<draw(state); + + + static int s_frameNumber = 0xffffffff; + static unsigned int s_NumberQuads = 0; + static unsigned int s_NumberQuadsVertices = 0; + static unsigned int s_NumberLines = 0; + static unsigned int s_NumberLinesVertices = 0; + static unsigned int s_NumberPoints = 0; + static unsigned int s_NumberPointsVertices = 0; + + if (s_frameNumber != state.getFrameStamp()->getFrameNumber()) + { + // std::cout<<"Frame "<< s_frameNumber<<"\tquads "<getFrameNumber(); + } + + + if (_internalGeometry->getName()=="quad") + { + s_NumberQuads++; + s_NumberQuadsVertices+= _internalGeometry->getVertexArray()->getNumElements(); + } + else if (_internalGeometry->getName()=="line") + { + s_NumberLines++; + s_NumberLinesVertices+= _internalGeometry->getVertexArray()->getNumElements(); + } + else if (_internalGeometry->getName()=="point") + { + s_NumberPoints++; + s_NumberPointsVertices+= _internalGeometry->getVertexArray()->getNumElements(); + } } virtual osg::BoundingBox computeBound() const @@ -212,6 +340,8 @@ void createGeometry(unsigned int numParticles, osg::Vec2Array* quad_offsets = 0; if (quad_geometry) { + quad_geometry->setName("quad"); + quad_vertices = new osg::Vec3Array(numParticles*4); quad_offsets = new osg::Vec2Array(numParticles*4); @@ -225,6 +355,8 @@ void createGeometry(unsigned int numParticles, osg::Vec2Array* line_offsets = 0; if (line_geometry) { + line_geometry->setName("line"); + line_vertices = new osg::Vec3Array(numParticles*2); line_offsets = new osg::Vec2Array(numParticles*2); @@ -238,6 +370,8 @@ void createGeometry(unsigned int numParticles, osg::Vec2Array* point_offsets = 0; if (point_geometry) { + point_geometry->setName("point"); + point_vertices = new osg::Vec3Array(numParticles); point_offsets = new osg::Vec2Array(numParticles); @@ -352,21 +486,19 @@ void setUpGeometries(unsigned int numParticles) } -osg::Node* createRainEffect(const osg::BoundingBox& bb, const osg::Vec3& velocity) +osg::Node* createRainEffect(const osg::BoundingBox& bb, const osg::Vec3& velocity, float nearTransition, float farTransition) { osg::LOD* lod = new osg::LOD; - // time taken to get from start to the end of cycle - float period = fabs((bb.zMax()-bb.zMin()) / velocity.z()); // distance between start point and end of cyclce osg::Vec3 position(bb.xMin(), bb.yMin(), bb.zMax()); + + // time taken to get from start to the end of cycle + float period = fabs((bb.zMax()-bb.zMin()) / velocity.z()); osg::Vec3 dv_i( bb.xMax()-bb.xMin(), 0.0f, 0.0f ); osg::Vec3 dv_j( 0.0f, bb.yMax()-bb.yMin(), 0.0f ); osg::Vec3 dv_k( velocity * period ); - - float nearDistance = 25.0; - float farDistance = 100.0; // high res LOD. { @@ -376,45 +508,50 @@ osg::Node* createRainEffect(const osg::BoundingBox& bb, const osg::Vec3& velocit highres_geode->addDrawable(geometry); + geometry->setName("highres"); geometry->setPosition(position); geometry->setInitialBound(bb); geometry->setInternalGeometry(quad_geometry.get()); geometry->setStateSet(quad_stateset.get()); - lod->addChild( highres_geode, 0.0f, nearDistance ); + lod->addChild( highres_geode, 0.0f, nearTransition ); } // low res LOD { osg::Geode* lowres_geode = new osg::Geode; + PrecipitationGeometry* geometry = new PrecipitationGeometry; lowres_geode->addDrawable(geometry); + geometry->setName("lowres"); geometry->setPosition(position); geometry->setInitialBound(bb); geometry->setInternalGeometry(point_geometry.get()); geometry->setStateSet(point_stateset.get()); - lod->addChild( lowres_geode, nearDistance, farDistance ); + lod->addChild( lowres_geode, nearTransition, farTransition ); } return lod; } -osg::Node* createCellRainEffect(const osg::BoundingBox& bb, const osg::Vec3& velocity, unsigned int numParticles) +osg::Node* createCellRainEffect(const PrecipatationParameters& parameters) { - unsigned int numX = 100; - unsigned int numY = 100; + unsigned int numX = parameters.numberOfCellsX; + unsigned int numY = parameters.numberOfCellsY; unsigned int numCells = numX*numY; - unsigned int numParticlesPerCell = numParticles/numCells; + unsigned int numParticlesPerCell = parameters.numberOfParticles/numCells; setUpGeometries(numParticlesPerCell); - std::cout<<"Effect total number of particles = "<setTextureAttribute(0, texture); - stateset->addUniform(new osg::Uniform("particleColour", osg::Vec4(0.6,0.6,0.6,1.0))); - stateset->addUniform(new osg::Uniform("particleSize", 0.02f)); + stateset->addUniform(new osg::Uniform("particleColour", parameters.particleColour)); + stateset->addUniform(new osg::Uniform("particleSize", parameters.particleSize)); osg::Uniform* previousModelViewUniform = new osg::Uniform("previousModelViewMatrix",osg::Matrix()); stateset->addUniform(previousModelViewUniform); group->setCullCallback(new CullCallback(previousModelViewUniform)); -#endif + return group; } -osg::Node* createModel(osg::Node* loadedModel, bool /*useShaders*/) +osg::Node* createModel(osg::Node* loadedModel, PrecipatationParameters& parameters) { osg::Group* group = new osg::Group; @@ -507,6 +643,8 @@ osg::Node* createModel(osg::Node* loadedModel, bool /*useShaders*/) bb.set( -500, -500, 0, +500, +500, 10); + parameters.boundingBox = bb; + osg::StateSet* stateset = loadedModel->getOrCreateStateSet(); osg::Fog* fog = new osg::Fog; @@ -530,7 +668,7 @@ osg::Node* createModel(osg::Node* loadedModel, bool /*useShaders*/) } - group->addChild(createCellRainEffect(bb, velocity, numParticles)); + group->addChild(createCellRainEffect(parameters)); return group; } @@ -559,9 +697,21 @@ int main( int argc, char **argv ) // get details on keyboard and mouse bindings used by the viewer. viewer.getUsage(*arguments.getApplicationUsage()); - bool shader = true; - while (arguments.read("--shader")) shader = true; - while (arguments.read("--fixed")) shader = false; + PrecipatationParameters parameters; + + float intensity; + while (arguments.read("--snow", intensity)) parameters.snow(intensity); + while (arguments.read("--rain", intensity)) parameters.rain(intensity); + + float particleSize; + while (arguments.read("--particleSize", particleSize)) parameters.particleSize = particleSize; + + osg::Vec3 particleVelocity; + while (arguments.read("--particleVelocity", particleVelocity.x(), particleVelocity.y(), particleVelocity.z() )) parameters.particleVelocity = particleVelocity; + + float transition; + while (arguments.read("--nearTransition", transition )) parameters.nearTransition = transition; + while (arguments.read("--farTransition", transition )) parameters.farTransition = transition; // if user request help write it out to cout. if (arguments.read("-h") || arguments.read("--help")) @@ -586,7 +736,7 @@ int main( int argc, char **argv ) // read the scene from the list of file specified commandline args. osg::ref_ptr loadedModel = osgDB::readNodeFiles(arguments); - loadedModel = createModel(loadedModel.get(), shader); + loadedModel = createModel(loadedModel.get(), parameters); // if no model has been successfully loaded report failure. if (!loadedModel) diff --git a/examples/osgprecipitation/point_rain.vert b/examples/osgprecipitation/point_rain.vert index 78986c6e8..684f2d1d1 100644 --- a/examples/osgprecipitation/point_rain.vert +++ b/examples/osgprecipitation/point_rain.vert @@ -24,8 +24,10 @@ void main(void) gl_Position = gl_ModelViewProjectionMatrix * vec4(v_current,1.0); - float pointSize = min(abs(1280*particleSize / gl_Position.w), 20.0); - gl_PointSize = max(ceil(pointSize),2); + //float pointSize = min(abs(1280*particleSize / gl_Position.w), 20.0); + float pointSize = abs(1280*particleSize / gl_Position.w); + //gl_PointSize = max(ceil(pointSize),2); + gl_PointSize = ceil(pointSize); - colour.a = 0.05+(pointSize)/(gl_PointSize); + colour.a = 0.05+(pointSize*pointSize)/(gl_PointSize*gl_PointSize); } diff --git a/examples/osgprecipitation/quad_rain.vert b/examples/osgprecipitation/quad_rain.vert index 0e2388069..c98054dea 100644 --- a/examples/osgprecipitation/quad_rain.vert +++ b/examples/osgprecipitation/quad_rain.vert @@ -35,8 +35,8 @@ void main(void) dv.xy += dv_normalized * particleSize; vec2 dp = vec2( -dv_normalized.y, dv_normalized.x ) * particleSize; - float area = length(dv.xy)*length(dp); - colour.a = 0.05+(particleSize*particleSize)/area; + float area = length(dv.xy); + colour.a = 0.05+(particleSize)/area; v1.xyz += dv*texCoord.y;