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

Revision 5092, 29.1 kB (checked in by robert, 8 years ago)

Further tweaks to settings to improve performance at mid intensity ranges

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