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

Revision 5090, 28.6 kB (checked in by robert, 8 years ago)

Added fog parameters settings.

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