root/OpenSceneGraph/trunk/examples/osgprecipitation/osgprecipitation.cpp @ 5088

Revision 5088, 27.3 kB (checked in by robert, 8 years ago)

Added --numberOfParticles, --numberOfCellsX, --numberOfCellsY, --numberOfCellsZ, --boundingBox, --fogEnd and --fogDensity controls

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
2 *
3 * This application is open source and may be redistributed and/or modified   
4 * freely and without restriction, both in commericial and non commericial applications,
5 * as long as this copyright notice is maintained.
6 *
7 * This application is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10*/
11
12#include <osgDB/ReadFile>
13#include <osgDB/FileUtils>
14#include <osgUtil/Optimizer>
15#include <osgUtil/CullVisitor>
16#include <osgProducer/Viewer>
17
18#include <osg/Point>
19#include <osg/BlendFunc>
20#include <osg/Texture2D>
21#include <osg/PointSprite>
22#include <osg/Program>
23#include <osg/Fog>
24#include <osg/Point>
25#include <osg/PointSprite>
26#include <osg/io_utils>
27
28float random(float min,float max) { return min + (max-min)*(float)rand()/(float)RAND_MAX; }
29
30struct PrecipatationParameters : public osg::Referenced
31{
32    PrecipatationParameters():
33        particleVelocity(0.0,0.0,-5.0),
34        particleSize(0.02),
35        particleColour(0.6, 0.6, 0.6, 1.0),
36        numberOfParticles(10000000),
37        numberOfCellsX(100),
38        numberOfCellsY(100),
39        numberOfCellsZ(1),
40        nearTransition(25.0),
41        farTransition(100.0),
42        fogDensity(0.1),
43        fogEnd(1000.0)
44    {}
45
46    void rain (float intensity)
47    {
48        particleVelocity = osg::Vec3(0.0,0.0,-2.0) + osg::Vec3(0.0,0.0,-10.0)*intensity;
49        particleSize = 0.01 + 0.02*intensity;
50        numberOfParticles = intensity * 100000000;
51        particleColour = osg::Vec4(0.6, 0.6, 0.6, 1.0);
52        fogDensity = intensity;
53        fogEnd = 250/(0.01 + intensity);
54    }
55
56    void snow(float intensity)
57    {
58        particleVelocity = osg::Vec3(0.0,0.0,-1.0) + osg::Vec3(0.0,0.0,-0.5)*intensity;
59        particleSize = 0.02 + 0.03*intensity;
60        numberOfParticles = intensity * 100000000;
61        particleColour = osg::Vec4(0.8, 0.8, 0.8, 1.0);
62        fogDensity = intensity;
63        fogEnd = 150/(0.01 + intensity);
64    }
65
66    osg::BoundingBox    boundingBox;
67    osg::Vec3           particleVelocity;
68    float               particleSize;
69    osg::Vec4           particleColour;
70    unsigned int        numberOfParticles;
71    unsigned int        numberOfCellsX;
72    unsigned int        numberOfCellsY;
73    unsigned int        numberOfCellsZ;
74    float               nearTransition;
75    float               farTransition;
76    float               fogDensity;
77    float               fogEnd;
78};
79
80struct PrecipitationCullCallback : public virtual osg::Drawable::CullCallback
81{
82    PrecipitationCullCallback() {}
83
84    PrecipitationCullCallback(const PrecipitationCullCallback&,const osg::CopyOp&) {}
85
86    META_Object(osg,PrecipitationCullCallback);
87
88    /** do customized cull code, return true if drawable should be culled.*/
89    virtual bool cull(osg::NodeVisitor* nodeVisitor, osg::Drawable* drawable, osg::State* state) const
90    {
91        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nodeVisitor);
92        if (cv)
93        {
94            float distance = nodeVisitor->getDistanceFromEyePoint(drawable->getBound().center(),true);
95
96//            if (distance<-4.0) return true;
97           
98#if 0
99           
100            const osg::BoundingBox& bb = drawable->getBound();
101            const osg::Polytope& frustum = cv->getCurrentCullingSet().getFrustum();
102            int numPointsInside = 0;
103            for(unsigned int i=0; i<8; ++i)
104            {
105                if (frustum.contains(bb.corner(i))) ++numPointsInside;
106            }
107       
108            std::cout<<" "<<drawable->getName()<<" distance "<<distance<<"num Points inside = "<<numPointsInside<<std::endl;
109
110            if (cv->isCulled(drawable->getBound()))
111            {
112                std::cout<<" isCulled "<<drawable->getName()<<std::endl;
113                return true;
114            }
115#endif
116
117        }
118   
119        return false;
120    }
121};
122
123
124class PrecipitationGeometry : public osg::Geometry
125{
126public:
127
128        PrecipitationGeometry()
129        {
130            setSupportsDisplayList(false);
131           
132            setCullCallback(new PrecipitationCullCallback());
133        }
134
135        virtual bool supports(const osg::PrimitiveFunctor&) const { return false; }
136        virtual void accept(osg::PrimitiveFunctor&) const {}
137        virtual bool supports(const osg::PrimitiveIndexFunctor&) const { return false; }
138        virtual void accept(osg::PrimitiveIndexFunctor&) const {}
139
140        void setInternalGeometry(osg::Geometry* geometry) { _internalGeometry = geometry; }
141       
142        osg::Geometry* getInternalGeometry() { return _internalGeometry.get(); }
143       
144        void setPosition(const osg::Vec3& position) { _position = position; }
145        const osg::Vec3& getPosition() const { return _position; }
146
147       
148        virtual void compileGLObjects(osg::State& state) const
149        {
150            if (!_internalGeometry) return;
151
152            static bool s_interalGeometryCompiled = false;
153            if (!s_interalGeometryCompiled)
154            {
155                _internalGeometry->compileGLObjects(state);
156                s_interalGeometryCompiled = true;
157            }
158        }
159
160        virtual void drawImplementation(osg::State& state) const
161        {
162            if (!_internalGeometry) return;
163           
164            glNormal3fv(_position.ptr());
165
166            _internalGeometry->draw(state);
167           
168           
169            static int s_frameNumber = 0xffffffff;
170            static unsigned int s_NumberQuads = 0;
171            static unsigned int s_NumberQuadsVertices = 0;
172            static unsigned int s_NumberLines = 0;
173            static unsigned int s_NumberLinesVertices = 0;
174            static unsigned int s_NumberPoints = 0;
175            static unsigned int s_NumberPointsVertices = 0;
176           
177            if (s_frameNumber != state.getFrameStamp()->getFrameNumber())
178            {
179                // std::cout<<"Frame "<< s_frameNumber<<"\tquads "<<s_NumberQuads<<", "<<s_NumberQuadsVertices<<"  points "<<s_NumberPoints<<", "<<s_NumberPointsVertices<<std::endl;
180           
181                s_NumberQuads = 0;
182                s_NumberLines = 0;
183                s_NumberPoints = 0;
184                s_NumberQuadsVertices = 0;
185                s_NumberLinesVertices = 0;
186                s_NumberPointsVertices = 0;
187
188                s_frameNumber = state.getFrameStamp()->getFrameNumber();
189            }
190           
191           
192            if (_internalGeometry->getName()=="quad")
193            {
194                s_NumberQuads++;
195                s_NumberQuadsVertices+= _internalGeometry->getVertexArray()->getNumElements();
196            }
197            else if (_internalGeometry->getName()=="line")
198            {
199                s_NumberLines++;
200                s_NumberLinesVertices+= _internalGeometry->getVertexArray()->getNumElements();
201            }
202            else if (_internalGeometry->getName()=="point")
203            {
204                s_NumberPoints++;
205                s_NumberPointsVertices+= _internalGeometry->getVertexArray()->getNumElements();
206            }
207        }
208
209        virtual osg::BoundingBox computeBound() const
210        {
211            return osg::BoundingBox();
212        }
213       
214protected:       
215
216        osg::Vec3                   _position;
217        osg::ref_ptr<osg::Geometry> _internalGeometry;
218
219};
220
221class CullCallback : public osg::NodeCallback
222{
223public:
224
225    CullCallback(osg::Uniform* uniform):
226        _previousFrame(0),
227        _initialized(false),
228        _uniform(uniform)
229    {
230    }
231
232    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
233    {
234        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
235        if (cv)
236        {
237            if (!_initialized)
238            {
239                _previousModelViewMatrix = cv->getModelViewMatrix();
240                _previousFrame = nv->getFrameStamp()->getFrameNumber();
241                _initialized = true;
242            }
243       
244            _uniform->set(_previousModelViewMatrix);
245           
246            // osg::notify(osg::NOTICE)<<"Updating uniform "<<_previousModelViewMatrix<<std::endl;
247
248            traverse(node, nv);
249           
250            if (_previousFrame != nv->getFrameStamp()->getFrameNumber())
251            {
252                _previousModelViewMatrix = cv->getModelViewMatrix();
253                _previousFrame = nv->getFrameStamp()->getFrameNumber();
254            }
255        }
256        else
257        {
258            traverse(node, nv);
259        }
260    }
261   
262    int _previousFrame;
263    bool _initialized;
264    osg::Matrix _previousModelViewMatrix;
265    osg::ref_ptr<osg::Uniform> _uniform;   
266};
267
268void fillSpotLightImage(unsigned char* ptr, const osg::Vec4& centerColour, const osg::Vec4& backgroudColour, unsigned int size, float power)
269{
270    float mid = (float(size)-1.0f)*0.5f;
271    float div = 2.0f/float(size);
272    for(unsigned int r=0;r<size;++r)
273    {
274        //unsigned char* ptr = image->data(0,r,0);
275        for(unsigned int c=0;c<size;++c)
276        {
277            float dx = (float(c) - mid)*div;
278            float dy = (float(r) - mid)*div;
279            float r = powf(1.0f-sqrtf(dx*dx+dy*dy),power);
280            if (r<0.0f) r=0.0f;
281            osg::Vec4 color = centerColour*r+backgroudColour*(1.0f-r);
282            *ptr++ = (unsigned char)((color[0])*255.0f);
283            *ptr++ = (unsigned char)((color[1])*255.0f);
284            *ptr++ = (unsigned char)((color[2])*255.0f);
285            *ptr++ = (unsigned char)((color[3])*255.0f);
286        }
287    }
288}
289
290
291osg::Image* createSpotLightImage(const osg::Vec4& centerColour, const osg::Vec4& backgroudColour, unsigned int size, float power)
292{
293
294#if 0
295    osg::Image* image = new osg::Image;
296    unsigned char* ptr = image->data(0,0,0);
297    fillSpotLightImage(ptr, centerColour, backgroudColour, size, power);
298
299    return image;
300#else
301    osg::Image* image = new osg::Image;
302    osg::Image::MipmapDataType mipmapData;
303    unsigned int s = size;
304    unsigned int totalSize = 0;
305    unsigned i;
306    for(i=0; s>0; s>>=1, ++i)
307    {
308        if (i>0) mipmapData.push_back(totalSize);
309        totalSize += s*s*4;
310    }
311
312    unsigned char* ptr = new unsigned char[totalSize];
313    image->setImage(size, size, size, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, ptr, osg::Image::USE_NEW_DELETE,1);
314
315    image->setMipmapLevels(mipmapData);
316
317    s = size;
318    for(i=0; s>0; s>>=1, ++i)
319    {
320        fillSpotLightImage(ptr, centerColour, backgroudColour, s, power);
321        ptr += s*s*4;
322    }
323
324    return image;
325#endif   
326}
327
328/** create quad, line and point geometry data all with consistent particle positions.*/
329void createGeometry(unsigned int numParticles,
330                    osg::Geometry* quad_geometry,
331                    osg::Geometry* line_geometry,
332                    osg::Geometry* point_geometry)
333{
334    // particle corner offsets
335    osg::Vec2 offset00(0.0f,0.0f);
336    osg::Vec2 offset10(1.0f,0.0f);
337    osg::Vec2 offset01(0.0f,1.0f);
338    osg::Vec2 offset11(1.0f,1.0f);
339   
340    osg::Vec2 offset0(0.5f,0.0f);
341    osg::Vec2 offset1(0.5f,1.0f);
342
343    osg::Vec2 offset(0.5f,0.5f);
344
345
346    // configure quad_geometry;
347    osg::Vec3Array* quad_vertices = 0;
348    osg::Vec2Array* quad_offsets = 0;
349    if (quad_geometry)
350    {
351        quad_geometry->setName("quad");
352   
353        quad_vertices = new osg::Vec3Array(numParticles*4);
354        quad_offsets = new osg::Vec2Array(numParticles*4);
355
356        quad_geometry->setVertexArray(quad_vertices);
357        quad_geometry->setTexCoordArray(0, quad_offsets);
358        quad_geometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, numParticles*4));
359    }
360
361    // configure line_geometry;
362    osg::Vec3Array* line_vertices = 0;
363    osg::Vec2Array* line_offsets = 0;
364    if (line_geometry)
365    {
366        line_geometry->setName("line");
367
368        line_vertices = new osg::Vec3Array(numParticles*2);
369        line_offsets = new osg::Vec2Array(numParticles*2);
370
371        line_geometry->setVertexArray(line_vertices);
372        line_geometry->setTexCoordArray(0, line_offsets);
373        line_geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, numParticles*2));
374    }
375
376    // configure point_geometry;
377    osg::Vec3Array* point_vertices = 0;
378    osg::Vec2Array* point_offsets = 0;
379    if (point_geometry)
380    {
381        point_geometry->setName("point");
382
383        point_vertices = new osg::Vec3Array(numParticles);
384        point_offsets = new osg::Vec2Array(numParticles);
385
386        point_geometry->setVertexArray(point_vertices);
387        point_geometry->setTexCoordArray(0, point_offsets);
388        point_geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, numParticles));
389    }
390
391    // set up vertex attribute data.
392    for(unsigned int i=0; i< numParticles; ++i)
393    {
394        osg::Vec3 pos( random(0.0f, 1.0f), random(0.0f, 1.0f), random(0.0f, 1.0f));
395   
396        // quad particles
397        if (quad_vertices)
398        {
399            (*quad_vertices)[i*4] = pos;
400            (*quad_vertices)[i*4+1] = pos;
401            (*quad_vertices)[i*4+2] =  pos;
402            (*quad_vertices)[i*4+3] =  pos;
403            (*quad_offsets)[i*4] = offset00;
404            (*quad_offsets)[i*4+1] = offset01;
405            (*quad_offsets)[i*4+2] = offset11;
406            (*quad_offsets)[i*4+3] = offset10;
407        }
408               
409        // line particles
410        if (line_vertices)
411        {
412            (*line_vertices)[i*2] = pos;
413            (*line_vertices)[i*2+1] = pos;
414            (*line_offsets)[i*2] = offset0;
415            (*line_offsets)[i*2+1] = offset1;
416        }
417       
418        // point particles
419        if (point_vertices)
420        {
421            (*point_vertices)[i] = pos;
422            (*point_offsets)[i] = offset;
423        }
424    }
425}
426
427
428static osg::ref_ptr<osg::Geometry> quad_geometry = 0;
429static osg::ref_ptr<osg::StateSet> quad_stateset = 0;
430
431static osg::ref_ptr<osg::Geometry> line_geometry = 0;
432static osg::ref_ptr<osg::StateSet> line_stateset = 0;
433
434static osg::ref_ptr<osg::Geometry> point_geometry = 0;
435static osg::ref_ptr<osg::StateSet> point_stateset = 0;
436
437void setUpGeometries(unsigned int numParticles)
438{
439    {
440        quad_geometry = new osg::Geometry;
441        quad_geometry->setUseVertexBufferObjects(true);
442
443        quad_stateset = new osg::StateSet;
444        osg::Program* program = new osg::Program;
445        quad_stateset->setAttribute(program);
446        quad_stateset->setRenderBinDetails(13,"DepthSortedBin");
447
448        // get shaders from source
449        program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("quad_rain.vert")));
450        program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("rain.frag")));
451    }
452
453
454    {
455        line_geometry = new osg::Geometry;
456        line_geometry->setUseVertexBufferObjects(true);
457
458        line_stateset = new osg::StateSet;
459
460        osg::Program* program = new osg::Program;
461        line_stateset->setAttribute(program);
462        line_stateset->setRenderBinDetails(12,"DepthSortedBin");
463
464        // get shaders from source
465        program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("line_rain.vert")));
466        program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("rain.frag")));
467    }
468
469
470    {
471        point_geometry = new osg::Geometry;
472        point_geometry->setUseVertexBufferObjects(true);
473
474        point_stateset = new osg::StateSet;
475
476        osg::Program* program = new osg::Program;
477        point_stateset->setAttribute(program);
478
479        // get shaders from source
480        program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("point_rain.vert")));
481        program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("rain.frag")));
482
483        /// Setup the point sprites
484        osg::PointSprite *sprite = new osg::PointSprite();
485        point_stateset->setTextureAttributeAndModes(0, sprite, osg::StateAttribute::ON);
486
487        point_stateset->setMode(GL_VERTEX_PROGRAM_POINT_SIZE, osg::StateAttribute::ON);
488        point_stateset->setRenderBinDetails(11,"DepthSortedBin");
489
490    }
491
492    createGeometry(numParticles, quad_geometry.get(), line_geometry.get(), point_geometry.get());
493
494}
495
496
497osg::Node* createRainEffect(const osg::BoundingBox& bb, const osg::Vec3& velocity, float nearTransition, float farTransition)
498{
499    osg::LOD* lod = new osg::LOD;
500   
501
502    // distance between start point and end of cyclce
503    osg::Vec3 position(bb.xMin(), bb.yMin(), bb.zMax());
504
505    // time taken to get from start to the end of cycle
506    float period = fabs((bb.zMax()-bb.zMin()) / velocity.z());
507    osg::Vec3 dv_i( bb.xMax()-bb.xMin(), 0.0f, 0.0f );
508    osg::Vec3 dv_j( 0.0f, bb.yMax()-bb.yMin(), 0.0f );
509    osg::Vec3 dv_k( velocity * period );
510   
511    // high res LOD.
512    {
513        osg::Geode* highres_geode = new osg::Geode;
514
515        PrecipitationGeometry* geometry = new PrecipitationGeometry;
516
517        highres_geode->addDrawable(geometry);
518
519        geometry->setName("highres");
520        geometry->setPosition(position);
521        geometry->setInitialBound(bb);
522        geometry->setInternalGeometry(quad_geometry.get());
523        geometry->setStateSet(quad_stateset.get());
524       
525        lod->addChild( highres_geode, 0.0f, nearTransition );
526    }
527   
528    // low res LOD
529    {
530        osg::Geode* lowres_geode = new osg::Geode;
531
532
533        PrecipitationGeometry* geometry = new PrecipitationGeometry;
534
535        lowres_geode->addDrawable(geometry);
536
537        geometry->setName("lowres");
538        geometry->setPosition(position);
539        geometry->setInitialBound(bb);
540        geometry->setInternalGeometry(point_geometry.get());
541        geometry->setStateSet(point_stateset.get());
542       
543        lod->addChild( lowres_geode, nearTransition, farTransition );
544    }
545
546
547    return lod;
548}
549
550osg::Node* createCellRainEffect(const PrecipatationParameters& parameters)
551{
552   
553    unsigned int numX = parameters.numberOfCellsX;
554    unsigned int numY = parameters.numberOfCellsY;
555    unsigned int numCells = numX*numY;
556    unsigned int numParticlesPerCell = parameters.numberOfParticles/numCells;
557
558    setUpGeometries(numParticlesPerCell);
559   
560    const osg::BoundingBox& bb = parameters.boundingBox;
561   
562    std::cout<<"Effect total number of particles = "<<parameters.numberOfParticles<<std::endl;
563    std::cout<<"Number of cells = "<<numCells<<std::endl;
564    std::cout<<"Number of particles per cell = "<<numParticlesPerCell<<std::endl;
565    std::cout<<"Cell width = "<<(bb.xMax()-bb.xMin())/(float)(numX)<<std::endl;
566    std::cout<<"Cell length = "<<(bb.yMax()-bb.yMin())/(float)(numY)<<std::endl;
567    std::cout<<"Cell height = "<<(bb.zMax()-bb.zMin())<<std::endl;
568
569    osg::Group* group = new osg::Group;
570    for(unsigned int i=0; i<numX; ++i)
571    {
572        for(unsigned int j=0; j<numX; ++j)
573        {
574            osg::BoundingBox bbLocal(bb.xMin() + ((bb.xMax()-bb.xMin())*(float)i)/(float)(numX),
575                                     bb.yMin() + ((bb.yMax()-bb.yMin())*(float)j)/(float)(numY),
576                                     bb.zMin(),
577                                     bb.xMin() + ((bb.xMax()-bb.xMin())*(float)(i+1))/(float)(numX),
578                                     bb.yMin() + ((bb.yMax()-bb.yMin())*(float)(j+1))/(float)(numY),
579                                     bb.zMax());
580
581            group->addChild(createRainEffect(bbLocal, parameters.particleVelocity, parameters.nearTransition, parameters.farTransition));
582        }       
583    }
584   
585
586    osgUtil::Optimizer::SpatializeGroupsVisitor sgv;
587    group->accept(sgv);
588    sgv.divide();
589
590
591    osg::StateSet* stateset = group->getOrCreateStateSet();
592
593    // time taken to get from start to the end of cycle
594    float period = fabs((bb.zMax()-bb.zMin()) / parameters.particleVelocity.z());
595
596    // distance between start point and end of cyclce
597    osg::Vec3 dv_i( (bb.xMax()-bb.xMin())/(float)(numX), 0.0f, 0.0f );
598    osg::Vec3 dv_j( 0.0f, (bb.yMax()-bb.yMin())/(float)(numY), 0.0f );
599    osg::Vec3 dv_k( parameters.particleVelocity * period );
600
601    // set up uniforms
602    // osg::Uniform* position_Uniform = new osg::Uniform("position",position);
603    osg::Uniform* dv_i_Uniform = new osg::Uniform("dv_i",dv_i);
604    osg::Uniform* dv_j_Uniform = new osg::Uniform("dv_j",dv_j);
605    osg::Uniform* dv_k_Uniform = new osg::Uniform("dv_k",dv_k);
606
607    osg::Uniform* inversePeriodUniform = new osg::Uniform("inversePeriod",1.0f/period);
608    osg::Uniform* startTime = new osg::Uniform("startTime",0.0f);
609
610    //stateset->addUniform(position_Uniform); // vec3
611    stateset->addUniform(dv_i_Uniform); // vec3 could be float
612    stateset->addUniform(dv_j_Uniform); // vec3 could be float
613    stateset->addUniform(dv_k_Uniform); // vec3
614    stateset->addUniform(inversePeriodUniform); // float
615    stateset->addUniform(startTime); // float
616
617    stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
618    stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
619
620    osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0);
621    stateset->addUniform(baseTextureSampler);
622
623    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));
624    stateset->setTextureAttribute(0, texture);
625
626    stateset->addUniform(new osg::Uniform("particleColour", parameters.particleColour));
627    stateset->addUniform(new osg::Uniform("particleSize", parameters.particleSize));
628 
629    osg::Uniform* previousModelViewUniform = new osg::Uniform("previousModelViewMatrix",osg::Matrix());
630    stateset->addUniform(previousModelViewUniform);
631   
632    group->setCullCallback(new CullCallback(previousModelViewUniform));
633
634
635    return group;
636}
637
638osg::Node* createModel(osg::Node* loadedModel, PrecipatationParameters& parameters)
639{
640    osg::Group* group = new osg::Group;
641
642    osg::BoundingBox bb(0.0, 0.0, 0.0, 100.0, 100.0, 100.0);
643    osg::Vec3 velocity(0.0,2.0,-8.0);
644    unsigned int numParticles = 50000000;
645   
646    if (loadedModel)
647    {
648        group->addChild(loadedModel);
649       
650        osg::BoundingSphere bs = loadedModel->getBound();
651
652        bb.set( -500, -500, 0, +500, +500, 10);
653       
654        parameters.boundingBox = bb;
655       
656        osg::StateSet* stateset = loadedModel->getOrCreateStateSet();
657       
658        osg::Fog* fog = new osg::Fog;
659        fog->setMode(osg::Fog::LINEAR);
660        fog->setDensity(parameters.fogDensity);
661        fog->setStart(0.0f);
662        fog->setEnd(parameters.fogEnd);
663        fog->setColor(osg::Vec4(0.5f,0.5f,0.5f,1.0f));
664        stateset->setAttributeAndModes(fog, osg::StateAttribute::ON);
665       
666        osg::LightSource* lightSource = new osg::LightSource;
667        group->addChild(lightSource);
668
669        osg::Light* light = lightSource->getLight();
670        light->setLightNum(0);
671        light->setPosition(osg::Vec4(0.0f,0.0f,1.0f,0.0f)); // directional light from above
672        light->setAmbient(osg::Vec4(0.8f,0.8f,0.8f,1.0f));
673        light->setDiffuse(osg::Vec4(0.2f,0.2f,0.2f,1.0f));
674        light->setSpecular(osg::Vec4(0.2f,0.2f,0.2f,1.0f));
675
676               
677    }
678   
679    group->addChild(createCellRainEffect(parameters));
680
681    return group;   
682}
683
684int main( int argc, char **argv )
685{
686
687    // use an ArgumentParser object to manage the program arguments.
688    osg::ArgumentParser arguments(&argc,argv);
689   
690    // set up the usage document, in case we need to print out how to use this program.
691    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
692    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" example provides an interactive viewer for visualising point clouds..");
693    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
694    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
695    arguments.getApplicationUsage()->addCommandLineOption("--shader","Use GLSL shaders.");
696    arguments.getApplicationUsage()->addCommandLineOption("--fixed","Use fixed function pipeline.");
697   
698
699    // construct the viewer.
700    osgProducer::Viewer viewer(arguments);
701
702    // set up the value with sensible default event handlers.
703    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
704
705    // get details on keyboard and mouse bindings used by the viewer.
706    viewer.getUsage(*arguments.getApplicationUsage());
707
708    PrecipatationParameters parameters;
709
710    float intensity;
711    while (arguments.read("--snow", intensity)) parameters.snow(intensity);
712    while (arguments.read("--rain", intensity)) parameters.rain(intensity);
713
714    while (arguments.read("--particleSize", parameters.particleSize)) {}
715
716    osg::Vec3 particleVelocity;
717    while (arguments.read("--particleVelocity", particleVelocity.x(), particleVelocity.y(), particleVelocity.z() )) parameters.particleVelocity = particleVelocity;
718
719    while (arguments.read("--nearTransition", parameters.nearTransition )) {}
720    while (arguments.read("--farTransition", parameters.farTransition )) {}
721
722    while (arguments.read("--numberOfParticles", parameters.numberOfParticles )) {}
723
724    while (arguments.read("--numberOfCellsX", parameters.numberOfCellsX )) {}
725    while (arguments.read("--numberOfCellsY", parameters.numberOfCellsY )) {}
726    while (arguments.read("--numberOfCellsZ", parameters.numberOfCellsZ )) {}
727
728    while (arguments.read("--boundingBox", parameters.boundingBox.xMin(),
729                                           parameters.boundingBox.yMin(),
730                                           parameters.boundingBox.zMin(),
731                                           parameters.boundingBox.xMax(),
732                                           parameters.boundingBox.yMax(),
733                                           parameters.boundingBox.zMax())) {}
734
735    while (arguments.read("--fogDensity", parameters.fogDensity )) {}
736    while (arguments.read("--fogEnd", parameters.fogEnd )) {}
737 
738    // if user request help write it out to cout.
739    if (arguments.read("-h") || arguments.read("--help"))
740    {
741        arguments.getApplicationUsage()->write(std::cout);
742        return 1;
743    }
744
745    // any option left unread are converted into errors to write out later.
746    arguments.reportRemainingOptionsAsUnrecognized();
747
748    // report any errors if they have occured when parsing the program aguments.
749    if (arguments.errors())
750    {
751        arguments.writeErrorMessages(std::cout);
752        return 1;
753    }
754   
755    osg::Timer timer;
756    osg::Timer_t start_tick = timer.tick();
757
758    // read the scene from the list of file specified commandline args.
759    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
760   
761    loadedModel = createModel(loadedModel.get(), parameters);
762
763    // if no model has been successfully loaded report failure.
764    if (!loadedModel)
765    {
766        std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
767        return 1;
768    }
769
770    osg::Timer_t end_tick = timer.tick();
771
772    std::cout << "Time to load = "<<timer.delta_s(start_tick,end_tick)<<std::endl;
773
774    // optimize the scene graph, remove rendundent nodes and state etc.
775    osgUtil::Optimizer optimizer;
776    // optimizer.optimize(loadedModel.get());
777
778    // set the scene to render
779    viewer.setSceneData(loadedModel.get());
780
781    // create the windows and run the threads.
782    viewer.realize();
783
784    while( !viewer.done() )
785    {
786        // wait for all cull and draw threads to complete.
787        viewer.sync();
788
789        // update the scene by traversing it with the the update visitor which will
790        // call all node update callbacks and animations.
791        viewer.update();
792         
793        // fire off the cull and draw traversals of the scene.
794        viewer.frame();
795       
796    }
797   
798    // wait for all cull and draw threads to complete before exit.
799    viewer.sync();
800
801    return 0;
802}
Note: See TracBrowser for help on using the browser.