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

Revision 5091, 29.1 kB (checked in by robert, 9 years ago)

Refined the default settings for rain and snow to achieve better framerates.

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