root/OpenSceneGraph/trunk/examples/osgshaderterrain/osgshaderterrain.cpp @ 4600

Revision 4600, 23.8 kB (checked in by robert, 9 years ago)

Fixed compile warnings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/AlphaFunc>
2#include <osg/Billboard>
3#include <osg/BlendFunc>
4#include <osg/Depth>
5#include <osg/Geode>
6#include <osg/Geometry>
7#include <osg/Material>
8#include <osg/Math>
9#include <osg/MatrixTransform>
10#include <osg/PolygonOffset>
11#include <osg/Projection>
12#include <osg/ShapeDrawable>
13#include <osg/StateSet>
14#include <osg/Switch>
15#include <osg/Texture2D>
16
17#include <osgDB/ReadFile>
18#include <osgDB/FileUtils>
19
20#include <osgUtil/IntersectVisitor>
21#include <osgUtil/SmoothingVisitor>
22
23#include <osgText/Text>
24
25#include <osgProducer/Viewer>
26
27// for the grid data..
28#include "../osghangglide/terrain_coords.h"
29
30// class to create the forest and manage the movement between various techniques.
31class ForestTechniqueManager : public osg::Referenced
32{
33public:
34
35    ForestTechniqueManager() {}
36
37    class Tree : public osg::Referenced
38    {
39    public:
40
41        Tree():
42            _color(255,255,255,255),
43            _width(1.0f),
44            _height(1.0f),
45            _type(0) {}
46
47        Tree(const osg::Vec3& position, const osg::Vec4ub& color, float width, float height, unsigned int type):
48            _position(position),
49            _color(color),
50            _width(width),
51            _height(height),
52            _type(type) {}
53
54        osg::Vec3       _position;
55        osg::Vec4ub     _color;
56        float           _width;
57        float           _height;
58        unsigned int    _type;
59    };
60   
61    typedef std::vector< osg::ref_ptr<Tree> > TreeList;
62   
63    class Cell : public osg::Referenced
64    {
65    public:
66        typedef std::vector< osg::ref_ptr<Cell> > CellList;
67
68        Cell():_parent(0) {}
69        Cell(osg::BoundingBox& bb):_parent(0), _bb(bb) {}
70       
71        void addCell(Cell* cell) { cell->_parent=this; _cells.push_back(cell); }
72
73        void addTree(Tree* tree) { _trees.push_back(tree); }
74       
75        void addTrees(const TreeList& trees) { _trees.insert(_trees.end(),trees.begin(),trees.end()); }
76       
77        void computeBound();
78       
79        bool contains(const osg::Vec3& position) const { return _bb.contains(position); }
80       
81        bool divide(unsigned int maxNumTreesPerCell=10);
82       
83        bool devide(bool xAxis, bool yAxis, bool zAxis);
84       
85        void bin();
86
87
88        Cell*               _parent;
89        osg::BoundingBox    _bb;
90        CellList            _cells;
91        TreeList            _trees;
92       
93    };
94
95    float random(float min,float max) { return min + (max-min)*(float)rand()/(float)RAND_MAX; }
96    int random(int min,int max) { return min + (int)((float)(max-min)*(float)rand()/(float)RAND_MAX); }
97
98    osg::Geode* createTerrain(const osg::Vec3& origin, const osg::Vec3& size);
99
100    void createTreeList(osg::Node* terrain,const osg::Vec3& origin, const osg::Vec3& size,unsigned int numTreesToCreate,TreeList& trees);
101
102    osg::Geometry* createOrthogonalQuadsNoColor( const osg::Vec3& pos, float w, float h );
103
104    osg::Node* createShaderGraph(Cell* cell,osg::StateSet* stateset);
105
106    osg::Node* createScene(unsigned int numTreesToCreates);
107   
108
109};
110
111// event handler to capture keyboard events and use them to advance the technique used for rendering
112void ForestTechniqueManager::Cell::computeBound()
113{
114    _bb.init();
115    for(CellList::iterator citr=_cells.begin();
116        citr!=_cells.end();
117        ++citr)
118    {
119        (*citr)->computeBound();
120        _bb.expandBy((*citr)->_bb);
121    }
122
123    for(TreeList::iterator titr=_trees.begin();
124        titr!=_trees.end();
125        ++titr)
126    {
127        _bb.expandBy((*titr)->_position);
128    }
129}
130
131bool ForestTechniqueManager::Cell::divide(unsigned int maxNumTreesPerCell)
132{
133
134    if (_trees.size()<=maxNumTreesPerCell) return false;
135
136    computeBound();
137
138    float radius = _bb.radius();
139    float divide_distance = radius*0.7f;
140    if (devide((_bb.xMax()-_bb.xMin())>divide_distance,(_bb.yMax()-_bb.yMin())>divide_distance,(_bb.zMax()-_bb.zMin())>divide_distance))
141    {
142        // recusively divide the new cells till maxNumTreesPerCell is met.
143        for(CellList::iterator citr=_cells.begin();
144            citr!=_cells.end();
145            ++citr)
146        {
147            (*citr)->divide(maxNumTreesPerCell);
148        }
149        return true;
150   }
151   else
152   {
153        return false;
154   }
155}
156
157bool ForestTechniqueManager::Cell::devide(bool xAxis, bool yAxis, bool zAxis)
158{
159    if (!(xAxis || yAxis || zAxis)) return false;
160
161    if (_cells.empty())
162        _cells.push_back(new Cell(_bb));
163
164    if (xAxis)
165    {
166        unsigned int numCellsToDivide=_cells.size();
167        for(unsigned int i=0;i<numCellsToDivide;++i)
168        {
169            Cell* orig_cell = _cells[i].get();
170            Cell* new_cell = new Cell(orig_cell->_bb);
171
172            float xCenter = (orig_cell->_bb.xMin()+orig_cell->_bb.xMax())*0.5f;
173            orig_cell->_bb.xMax() = xCenter;
174            new_cell->_bb.xMin() = xCenter;
175
176            _cells.push_back(new_cell);
177        }
178    }
179
180    if (yAxis)
181    {
182        unsigned int numCellsToDivide=_cells.size();
183        for(unsigned int i=0;i<numCellsToDivide;++i)
184        {
185            Cell* orig_cell = _cells[i].get();
186            Cell* new_cell = new Cell(orig_cell->_bb);
187
188            float yCenter = (orig_cell->_bb.yMin()+orig_cell->_bb.yMax())*0.5f;
189            orig_cell->_bb.yMax() = yCenter;
190            new_cell->_bb.yMin() = yCenter;
191
192            _cells.push_back(new_cell);
193        }
194    }
195
196    if (zAxis)
197    {
198        unsigned int numCellsToDivide=_cells.size();
199        for(unsigned int i=0;i<numCellsToDivide;++i)
200        {
201            Cell* orig_cell = _cells[i].get();
202            Cell* new_cell = new Cell(orig_cell->_bb);
203
204            float zCenter = (orig_cell->_bb.zMin()+orig_cell->_bb.zMax())*0.5f;
205            orig_cell->_bb.zMax() = zCenter;
206            new_cell->_bb.zMin() = zCenter;
207
208            _cells.push_back(new_cell);
209        }
210    }
211
212    bin();
213
214    return true;
215
216}
217
218void ForestTechniqueManager::Cell::bin()
219{   
220    // put trees in apprpriate cells.
221    TreeList treesNotAssigned;
222    for(TreeList::iterator titr=_trees.begin();
223        titr!=_trees.end();
224        ++titr)
225    {
226        Tree* tree = titr->get();
227        bool assigned = false;
228        for(CellList::iterator citr=_cells.begin();
229            citr!=_cells.end() && !assigned;
230            ++citr)
231        {
232            if ((*citr)->contains(tree->_position))
233            {
234                (*citr)->addTree(tree);
235                assigned = true;
236            }
237        }
238        if (!assigned) treesNotAssigned.push_back(tree);
239    }
240
241    // put the unassigned trees back into the original local tree list.
242    _trees.swap(treesNotAssigned);
243
244
245    // prune empty cells.
246    CellList cellsNotEmpty;
247    for(CellList::iterator citr=_cells.begin();
248        citr!=_cells.end();
249        ++citr)
250    {
251        if (!((*citr)->_trees.empty()))
252        {
253            cellsNotEmpty.push_back(*citr);
254        }
255    }
256    _cells.swap(cellsNotEmpty);
257
258
259}
260
261
262void ForestTechniqueManager::createTreeList(osg::Node* terrain,const osg::Vec3& origin, const osg::Vec3& size,unsigned int numTreesToCreate,TreeList& trees)
263{
264
265    float max_TreeHeight = sqrtf(size.length2()/(float)numTreesToCreate);
266    float max_TreeWidth = max_TreeHeight*0.5f;
267   
268    float min_TreeHeight = max_TreeHeight*0.3f;
269    float min_TreeWidth = min_TreeHeight*0.5f;
270
271    trees.reserve(trees.size()+numTreesToCreate);
272
273
274    for(unsigned int i=0;i<numTreesToCreate;++i)
275    {
276        Tree* tree = new Tree;
277        tree->_position.set(random(origin.x(),origin.x()+size.x()),random(origin.y(),origin.y()+size.y()),origin.z());
278        tree->_color.set(random(128,255),random(128,255),random(128,255),255);
279        tree->_width = random(min_TreeWidth,max_TreeWidth);
280        tree->_height = random(min_TreeHeight,max_TreeHeight);
281        tree->_type = 0;
282       
283        if (terrain)
284        {
285            osgUtil::IntersectVisitor iv;
286            osg::ref_ptr<osg::LineSegment> segDown = new osg::LineSegment;
287
288            segDown->set(tree->_position,tree->_position+osg::Vec3(0.0f,0.0f,size.z()));
289            iv.addLineSegment(segDown.get());
290           
291            terrain->accept(iv);
292
293            if (iv.hits())
294            {
295                osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segDown.get());
296                if (!hitList.empty())
297                {
298                    osg::Vec3 ip = hitList.front().getWorldIntersectPoint();
299                    osg::Vec3 np = hitList.front().getWorldIntersectNormal();
300                    tree->_position = ip;
301                }
302            }
303        }
304       
305        trees.push_back(tree);
306    }
307}
308
309osg::Geometry* ForestTechniqueManager::createOrthogonalQuadsNoColor( const osg::Vec3& pos, float w, float h)
310{
311    // set up the coords
312    osg::Vec3Array& v = *(new osg::Vec3Array(8));
313    osg::Vec2Array& t = *(new osg::Vec2Array(8));
314   
315    float rotation = random(0.0f,osg::PI/2.0f);
316    float sw = sinf(rotation)*w*0.5f;
317    float cw = cosf(rotation)*w*0.5f;
318
319    v[0].set(pos.x()-sw,pos.y()-cw,pos.z()+0.0f);
320    v[1].set(pos.x()+sw,pos.y()+cw,pos.z()+0.0f);
321    v[2].set(pos.x()+sw,pos.y()+cw,pos.z()+h);
322    v[3].set(pos.x()-sw,pos.y()-cw,pos.z()+h);
323
324    v[4].set(pos.x()-cw,pos.y()+sw,pos.z()+0.0f);
325    v[5].set(pos.x()+cw,pos.y()-sw,pos.z()+0.0f);
326    v[6].set(pos.x()+cw,pos.y()-sw,pos.z()+h);
327    v[7].set(pos.x()-cw,pos.y()+sw,pos.z()+h);
328
329    t[0].set(0.0f,0.0f);
330    t[1].set(1.0f,0.0f);
331    t[2].set(1.0f,1.0f);
332    t[3].set(0.0f,1.0f);
333
334    t[4].set(0.0f,0.0f);
335    t[5].set(1.0f,0.0f);
336    t[6].set(1.0f,1.0f);
337    t[7].set(0.0f,1.0f);
338
339    osg::Geometry *geom = new osg::Geometry;
340
341    geom->setVertexArray( &v );
342
343    geom->setTexCoordArray( 0, &t );
344
345    geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,8) );
346
347    return geom;
348}
349
350class ShaderGeometry : public osg::Drawable
351{
352    public:
353        ShaderGeometry() { setUseDisplayList(false); }
354
355        /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
356        ShaderGeometry(const ShaderGeometry& ShaderGeometry,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
357            osg::Drawable(ShaderGeometry,copyop) {}
358
359        META_Object(osg,ShaderGeometry)
360
361        typedef std::vector<osg::Vec4> PositionSizeList;
362       
363        virtual void drawImplementation(osg::State& state) const
364        {
365            for(PositionSizeList::const_iterator itr = _trees.begin();
366                itr != _trees.end();
367                ++itr)
368            {
369                glColor4fv(itr->ptr());
370                _geometry->draw(state);
371            }
372        }
373
374        virtual osg::BoundingBox computeBound() const
375        {
376            osg::BoundingBox geom_box = _geometry->getBound();
377            osg::BoundingBox bb;
378            for(PositionSizeList::const_iterator itr = _trees.begin();
379                itr != _trees.end();
380                ++itr)
381            {
382                bb.expandBy(geom_box.corner(0)*(*itr)[3] +
383                            osg::Vec3( (*itr)[0], (*itr)[1], (*itr)[2] ));
384                bb.expandBy(geom_box.corner(7)*(*itr)[3] +
385                            osg::Vec3( (*itr)[0], (*itr)[1], (*itr)[2] ));
386            }
387            return bb;
388        }
389       
390        void setGeometry(osg::Geometry* geometry)
391        {
392            _geometry = geometry;
393        }
394       
395        void addTree(ForestTechniqueManager::Tree& tree)
396        {
397            _trees.push_back(osg::Vec4(tree._position.x(), tree._position.y(), tree._position.z(), tree._height));
398        }
399       
400        osg::ref_ptr<osg::Geometry> _geometry;
401
402        PositionSizeList _trees;
403
404    protected:
405   
406        virtual ~ShaderGeometry() {}
407       
408};
409
410osg::Geometry* shared_geometry = 0;
411
412osg::Node* ForestTechniqueManager::createShaderGraph(Cell* cell,osg::StateSet* stateset)
413{
414    if (shared_geometry==0)
415    {
416        shared_geometry = createOrthogonalQuadsNoColor(osg::Vec3(0.0f,0.0f,0.0f),1.0f,1.0f);
417        //shared_geometry->setUseDisplayList(false);
418    }
419
420
421    bool needGroup = !(cell->_cells.empty());
422    bool needTrees = !(cell->_trees.empty());
423   
424    osg::Geode* geode = 0;
425    osg::Group* group = 0;
426   
427    if (needTrees)
428    {
429        geode = new osg::Geode;
430       
431        ShaderGeometry* shader_geometry = new ShaderGeometry;
432        shader_geometry->setGeometry(shared_geometry);
433       
434       
435        for(TreeList::iterator itr=cell->_trees.begin();
436            itr!=cell->_trees.end();
437            ++itr)
438        {
439            Tree& tree = **itr;
440            shader_geometry->addTree(tree);
441
442        }
443
444        geode->setStateSet(stateset);
445        geode->addDrawable(shader_geometry);
446    }
447   
448    if (needGroup)
449    {
450        group = new osg::Group;
451        for(Cell::CellList::iterator itr=cell->_cells.begin();
452            itr!=cell->_cells.end();
453            ++itr)
454        {
455            group->addChild(createShaderGraph(itr->get(),stateset));
456        }
457       
458        if (geode) group->addChild(geode);
459       
460    }
461    if (group) return group;
462    else return geode;
463}
464
465osg::Node* ForestTechniqueManager::createScene(unsigned int /*numTreesToCreates*/)
466{
467    osg::Group* scene = new osg::Group;
468   
469    unsigned int numColumns = 38;
470    unsigned int numRows = 39;
471    unsigned int r;
472    unsigned int c;
473
474    osg::Vec3 origin(0.0f,0.0f,0.0f);
475    osg::Vec3 size(1000.0f,1000.0f,250.0f);
476    osg::Vec3 scaleDown(1.0f/size.x(),1.0f/size.y(),1.0f/size.z());
477
478    // ---------------------------------------
479    // Set up a StateSet to texture the objects
480    // ---------------------------------------
481    osg::StateSet* stateset = new osg::StateSet();
482
483
484    osg::Uniform* originUniform = new osg::Uniform("terrainOrigin",origin);
485    stateset->addUniform(originUniform);
486
487    osg::Uniform* sizeUniform = new osg::Uniform("terrainSize",size);
488    stateset->addUniform(sizeUniform);
489
490    osg::Uniform* scaleDownUniform = new osg::Uniform("terrainScaleDown",scaleDown);
491    stateset->addUniform(scaleDownUniform);
492
493    osg::Uniform* terrainTextureSampler = new osg::Uniform("terrainTexture",0);
494    stateset->addUniform(terrainTextureSampler);
495
496    osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",1);
497    stateset->addUniform(baseTextureSampler);
498
499    osg::Uniform* treeTextureSampler = new osg::Uniform("treeTexture",1);
500    stateset->addUniform(treeTextureSampler);
501
502
503    // compute z range of z values of grid data so we can scale it.
504    float min_z = FLT_MAX;
505    float max_z = -FLT_MAX;
506    for(r=0;r<numRows;++r)
507    {
508        for(c=0;c<numColumns;++c)
509        {
510            min_z = osg::minimum(min_z,vertex[r+c*numRows][2]);
511            max_z = osg::maximum(max_z,vertex[r+c*numRows][2]);
512        }
513    }
514       
515    float scale_z = size.z()/(max_z-min_z);
516
517    osg::Image* terrainImage = new osg::Image;
518    terrainImage->allocateImage(numColumns,numRows,1,GL_LUMINANCE, GL_FLOAT);
519    terrainImage->setInternalTextureFormat(GL_LUMINANCE_FLOAT32_ATI);
520    for(r=0;r<numRows;++r)
521    {
522        for(c=0;c<numColumns;++c)
523        {
524            *((float*)(terrainImage->data(c,r))) = (vertex[r+c*numRows][2]-min_z)*scale_z;
525        }
526    }
527   
528    osg::Texture2D* terrainTexture = new osg::Texture2D;
529    terrainTexture->setImage(terrainImage);
530    terrainTexture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
531    terrainTexture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
532    //terrainTexture->setResizeNonPowerOfTwoHint(true);
533    stateset->setTextureAttributeAndModes(0,terrainTexture,osg::StateAttribute::ON);
534
535
536    osg::Image* image = osgDB::readImageFile("Images/lz.rgb");
537    if (image)
538    {
539        osg::Texture2D* texture = new osg::Texture2D;
540       
541        texture->setImage(image);
542        stateset->setTextureAttributeAndModes(1,texture,osg::StateAttribute::ON);
543    }
544
545    {   
546        std::cout<<"Creating terrain...";
547
548        osg::Geode* geode = new osg::Geode();
549        geode->setStateSet( stateset );
550
551
552        {
553            osg::Program* program = new osg::Program;
554            stateset->setAttribute(program);
555
556#if 1
557            // use inline shaders
558           
559            ///////////////////////////////////////////////////////////////////
560            // vertex shader using just Vec4 coefficients
561            char vertexShaderSource[] =
562               "uniform float osg_FrameTime;\n"
563               "uniform sampler2D terrainTexture;\n"
564               "uniform vec3 terrainOrigin;\n"
565               "uniform vec3 terrainScaleDown;\n"
566               "\n"
567               "varying vec2 texcoord;\n"
568               "\n"
569               "void main(void)\n"
570               "{\n"
571               "    texcoord = gl_Vertex.xy - terrainOrigin.xy;\n"
572               "    texcoord.x *= terrainScaleDown.x;\n"
573               "    texcoord.y *= terrainScaleDown.y;\n"
574               "\n"
575               "    vec4 position;\n"
576               "    position.x = gl_Vertex.x;\n"
577               "    position.y = gl_Vertex.y;\n"
578               "    position.z = texture2D(terrainTexture, texcoord).r;\n"
579               " \n"
580               "    gl_Position     = gl_ModelViewProjectionMatrix * position;\n"
581                "   gl_FrontColor = vec4(1.0,1.0,1.0,1.0);\n"
582               "}\n";
583
584            //////////////////////////////////////////////////////////////////
585            // fragment shader
586            //
587            char fragmentShaderSource[] =
588                "uniform sampler2D baseTexture; \n"
589                "varying vec2 texcoord;\n"
590                "\n"
591                "void main(void) \n"
592                "{\n"
593                "    gl_FragColor = texture2D( baseTexture, texcoord); \n"
594                "}\n";
595
596            program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource));
597            program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource));
598           
599#else
600
601            // get shaders from source
602            program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("shaders/terrain.vert")));
603            program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("shaders/terrain.frag")));
604
605#endif
606
607            // get shaders from source
608        }
609
610
611        {
612            osg::Geometry* geometry = new osg::Geometry;
613
614            osg::Vec3Array& v = *(new osg::Vec3Array(numColumns*numRows));
615            osg::Vec4ubArray& color = *(new osg::Vec4ubArray(1));
616
617            color[0].set(255,255,255,255);
618
619            float rowCoordDelta = size.y()/(float)(numRows-1);
620            float columnCoordDelta = size.x()/(float)(numColumns-1);
621
622            float rowTexDelta = 1.0f/(float)(numRows-1);
623            float columnTexDelta = 1.0f/(float)(numColumns-1);
624
625            osg::Vec3 pos = origin;
626            osg::Vec2 tex(0.0f,0.0f);
627            int vi=0;
628            for(r=0;r<numRows;++r)
629            {
630                pos.x() = origin.x();
631                tex.x() = 0.0f;
632                for(c=0;c<numColumns;++c)
633                {
634                    v[vi].set(pos.x(),pos.y(),pos.z());
635                    pos.x()+=columnCoordDelta;
636                    tex.x()+=columnTexDelta;
637                    ++vi;
638                }
639                pos.y() += rowCoordDelta;
640                tex.y() += rowTexDelta;
641            }
642
643            geometry->setVertexArray(&v);
644            geometry->setColorArray(&color);
645            geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
646
647            for(r=0;r<numRows-1;++r)
648            {
649                osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_QUAD_STRIP,2*numColumns));
650                geometry->addPrimitiveSet(&drawElements);
651                int ei=0;
652                for(c=0;c<numColumns;++c)
653                {
654                    drawElements[ei++] = (r+1)*numColumns+c;
655                    drawElements[ei++] = (r)*numColumns+c;
656                }
657            }
658           
659            geometry->setInitialBound(osg::BoundingBox(origin, origin+size));
660
661            geode->addDrawable(geometry);
662
663            scene->addChild(geode);
664        }
665    }
666       
667    std::cout<<"done."<<std::endl;
668#if 0
669    std::cout<<"Creating tree locations...";std::cout.flush();
670    TreeList trees;
671    createTreeList(0,origin,size,numTreesToCreates,trees);
672    std::cout<<"done."<<std::endl;
673   
674    std::cout<<"Creating cell subdivision...";
675    osg::ref_ptr<Cell> cell = new Cell;
676    cell->addTrees(trees);
677    cell->divide();
678     std::cout<<"done."<<std::endl;
679   
680   
681    osg::Texture2D *tex = new osg::Texture2D;
682    tex->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP );
683    tex->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP );
684    tex->setImage(osgDB::readImageFile("Images/tree0.rgba"));
685
686    osg::StateSet *dstate = new osg::StateSet;
687    {   
688        dstate->setTextureAttributeAndModes(1, tex, osg::StateAttribute::ON );
689
690        dstate->setAttributeAndModes( new osg::BlendFunc, osg::StateAttribute::ON );
691
692        osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
693        alphaFunc->setFunction(osg::AlphaFunc::GEQUAL,0.05f);
694        dstate->setAttributeAndModes( alphaFunc, osg::StateAttribute::ON );
695
696        dstate->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
697
698        dstate->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
699    }
700   
701
702    {
703        osg::StateSet* stateset = new osg::StateSet;
704
705        stateset->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON );
706        stateset->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
707
708        {
709            osg::Program* program = new osg::Program;
710            stateset->setAttribute(program);
711
712            // get shaders from source
713            program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("shaders/forest2.vert")));
714            program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("shaders/forest2.frag")));
715        }
716
717        std::cout<<"Creating billboard based forest...";
718        scene->addChild(createShaderGraph(cell.get(),stateset));
719
720    }
721#endif
722
723    return scene;
724}
725
726int main( int argc, char **argv )
727{
728
729    // use an ArgumentParser object to manage the program arguments.
730    osg::ArgumentParser arguments(&argc,argv);
731
732    // set up the usage document, in case we need to print out how to use this program.
733    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates the osg::Shape classes.");
734    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
735    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
736    arguments.getApplicationUsage()->addCommandLineOption("--trees <number>","Set the number of trees to create");
737   
738    // construct the viewer.
739    osgProducer::Viewer viewer(arguments);
740
741    float numTreesToCreates = 10000;
742    arguments.read("--trees",numTreesToCreates);
743
744    // set up the value with sensible default event handlers.
745    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
746   
747    osg::ref_ptr<ForestTechniqueManager> ttm = new ForestTechniqueManager;
748   
749    // get details on keyboard and mouse bindings used by the viewer.
750    viewer.getUsage(*arguments.getApplicationUsage());
751
752    // if user request help write it out to cout.
753    if (arguments.read("-h") || arguments.read("--help"))
754    {
755        arguments.getApplicationUsage()->write(std::cout);
756        return 1;
757    }
758
759    // any option left unread are converted into errors to write out later.
760    arguments.reportRemainingOptionsAsUnrecognized();
761
762    // report any errors if they have occured when parsing the program aguments.
763    if (arguments.errors())
764    {
765        arguments.writeErrorMessages(std::cout);
766        return 1;
767    }
768   
769    osg::Node* node = ttm->createScene((unsigned int)numTreesToCreates);
770
771    // add model to viewer.
772    viewer.setSceneData( node );
773
774    // create the windows and run the threads.
775    viewer.realize();
776
777    while( !viewer.done() )
778    {
779        // wait for all cull and draw threads to complete.
780        viewer.sync();
781
782        // update the scene by traversing it with the the update visitor which will
783        // call all node update callbacks and animations.
784        viewer.update();
785         
786        // fire off the cull and draw traversals of the scene.
787        viewer.frame();
788       
789    }
790   
791    // wait for all cull and draw threads to complete before exit.
792    viewer.sync();
793
794    return 0;
795}
Note: See TracBrowser for help on using the browser.