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

Revision 5087, 26.2 kB (checked in by robert, 8 years ago)

Added command line options and various speed improvements.

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