root/OpenSceneGraph/trunk/examples/osgimpostor/osgimpostor.cpp @ 5927

Revision 5927, 9.4 kB (checked in by robert, 8 years ago)

Ported following examples to osgViewer:

osggeodemo
osggeometry
osghud
osgimpostor
osgkeyboard
osglauncher
osglight
osglightpoint
osglogicop
osglogo
osgmovie
osgmultiplecameras
osgmultitexture
osgoccluder
osgparametric
osgparticle

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/Geometry>
2#include <osg/Material>
3#include <osg/MatrixTransform>
4#include <osg/Quat>
5#include <osg/Geode>
6
7#include <osgSim/Impostor>
8#include <osgSim/InsertImpostorsVisitor>
9
10#include <osgDB/ReadFile>
11
12#include <osgViewer/Viewer>
13
14#include "TestManipulator.h"
15
16
17#include <iostream>
18#include <list>
19
20// container storing all house nodes
21typedef osg::ref_ptr<osg::Node>    NodePtr;
22typedef std::list<NodePtr>        NodeContainer;
23typedef NodeContainer::iterator    NodeIterator;
24
25NodeContainer                    nodes;
26
27//
28osg::Group * Root = 0;
29
30const int HOUSES_SIZE = 25000;        // total number of houses
31double XDim = 5000.0f;                // area dimension +/- XDim
32double ZDim = 5000.0f;                // area dimension +/- YDim
33
34int GridX = 20;                        // number of grids in x direction
35int GridY = 20;                        // number of grids in y direction
36
37bool UseImpostor = true;            // use impostor (or do not use)
38
39float Threshold = 3000.0f;            // distance where impostor are shown
40
41// create houses and store nodes in container
42void CreateHouses()
43{
44    int i;
45
46    GLubyte indices[48] = {
47        0, 2, 1,
48        3, 2, 0,
49        0, 4, 7,
50        7, 3, 0,
51        0, 1, 5,
52        5, 4, 0,
53        1, 6, 5,
54        2, 6, 1,
55        2, 3, 7,
56        2, 7, 6,
57        4, 8, 7,
58        5, 6, 9,
59        4, 5, 8,
60        8, 5, 9,
61        6, 7, 8,
62        8, 9, 6
63    };
64
65    // use the same color, normal and indices for all houses.
66        osg::Vec4Array* colors = new osg::Vec4Array(1);
67    (*colors)[0] = osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
68
69    // normals
70    osg::Vec3Array * normals = new osg::Vec3Array(16);
71    (*normals)[0] = osg::Vec3( 0.0f,  -0.0f, -1.0f);
72    (*normals)[1] = osg::Vec3( 0.0f,  -0.0f, -1.0f);
73    (*normals)[2] = osg::Vec3( 0.0f,  -1.0f,  0.0f);
74    (*normals)[3] = osg::Vec3( 0.0f,  -1.0f,  0.0f);
75    (*normals)[4] = osg::Vec3( 1.0f,  -0.0f,  0.0f);
76    (*normals)[5] = osg::Vec3( 1.0f,  -0.0f,  0.0f);
77    (*normals)[6] = osg::Vec3( 0.0f, 1.0f,  0.0f);
78    (*normals)[7] = osg::Vec3( 0.0f, 1.0f,  0.0f);
79    (*normals)[8] = osg::Vec3(-1.0f,  -0.0f,  0.0f);
80    (*normals)[9] = osg::Vec3(-1.0f,  -0.0f,  0.0f);
81    (*normals)[10] = osg::Vec3( 0.0f,  -0.928477f, 0.371391f);
82    (*normals)[11] = osg::Vec3( 0.0f, 0.928477f, 0.371391f);
83    (*normals)[12] = osg::Vec3( 0.707107f,  0.0f, 0.707107f);
84    (*normals)[13] = osg::Vec3( 0.707107f,  0.0f, 0.707107f);
85    (*normals)[14] = osg::Vec3(-0.707107f,  0.0f, 0.707107f);
86    (*normals)[15] = osg::Vec3(-0.707107f,  0.0f, 0.707107f);
87
88    // coordIndices
89    osg::UByteArray* coordIndices = new osg::UByteArray(48,indices);
90
91        // share the primtive set.
92        osg::PrimitiveSet* primitives = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,48);
93
94    for (int q = 0; q < HOUSES_SIZE; q++)
95    {
96        float xPos = ((static_cast<double> (rand()) /
97                      static_cast<double> (RAND_MAX))
98                     * 2.0 * XDim) - XDim;
99
100        float yPos = ((static_cast<double> (rand()) /
101                      static_cast<double> (RAND_MAX))
102                     * 2 * ZDim) - ZDim;
103
104        float scale = 10.0f;
105               
106                osg::Vec3 offset(xPos,yPos,0.0f);
107
108        // coords
109        osg::Vec3Array* coords = new osg::Vec3Array(10);
110        (*coords)[0] = osg::Vec3( 0.5f, -0.7f, 0.0f);
111        (*coords)[1] = osg::Vec3( 0.5f,  0.7f, 0.0f);
112        (*coords)[2] = osg::Vec3(-0.5f, 0.7f, 0.0f);
113        (*coords)[3] = osg::Vec3(-0.5f, -0.7f, 0.0f);
114        (*coords)[4] = osg::Vec3( 0.5f, -0.7f, 1.0f);
115        (*coords)[5] = osg::Vec3( 0.5f,  0.7f, 1.0f);
116        (*coords)[6] = osg::Vec3(-0.5f,  0.7f, 1.0f);
117        (*coords)[7] = osg::Vec3(-0.5f, -0.7f, 1.0f);
118        (*coords)[8] = osg::Vec3( 0.0f, -0.5f, 1.5f);
119        (*coords)[9] = osg::Vec3( 0.0f,  0.5f, 1.5f);
120
121        for (i = 0; i < 10; i++)
122        {
123            (*coords)[i] = (*coords)[i] * scale + offset;
124        }
125
126
127        // create geometry
128        osg::Geometry * geometry = new osg::Geometry();
129               
130        geometry->addPrimitiveSet(primitives);
131               
132        geometry->setVertexArray(coords);
133                geometry->setVertexIndices(coordIndices);
134               
135        geometry->setColorArray(colors);
136        geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
137               
138        geometry->setNormalArray(normals);
139        geometry->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
140
141        osg::Geode * geode = new osg::Geode();
142        geode->addDrawable(geometry);
143       
144        nodes.push_back(geode);
145    }
146}
147
148void LayoutAsGrid()
149{
150    // calculate bounding box
151    osg::BoundingBox bbox;
152    for (NodeIterator node = nodes.begin(); node != nodes.end(); ++node)
153        bbox.expandBy((*node)->getBound());
154
155    // setup grid information
156    osg::Group ** groups = new osg::Group*[GridX * GridY];
157        int i;
158    for (i = 0; i < GridX * GridY; i++)
159        groups[i] = new osg::Group();
160
161    float xGridStart = bbox.xMin();
162    float xGridSize = (bbox.xMax() - bbox.xMin()) / GridX;
163
164    float yGridStart = bbox.yMin();
165    float yGridSize = (bbox.yMax() - bbox.yMin()) / GridY;
166
167    // arrange buildings into right grid
168    for (NodeIterator nodeIter = nodes.begin(); nodeIter != nodes.end(); ++nodeIter)
169    {
170        osg::Node * node = nodeIter->get();
171        osg::Vec3 center = node->getBound().center();
172       
173        int x = (int)floor((center.x() - xGridStart) / xGridSize);
174        int z = (int)floor((center.y() - yGridStart) / yGridSize);
175
176        groups[z * GridX + x]->addChild(node);
177    }
178 
179    // add nodes to building root   
180    for (i = 0; i < GridX * GridY; i++)
181    {
182        osg::StateSet * stateset = new osg::StateSet();
183
184        osg::Material * material = new osg::Material();
185        osg::Vec4 color = osg::Vec4(
186            0.5f + (static_cast<double> (rand()) / (2.0*static_cast<double> (RAND_MAX))),
187            0.5f + (static_cast<double> (rand()) / (2.0*static_cast<double> (RAND_MAX))),
188            0.5f + (static_cast<double> (rand()) / ( 2.0*static_cast<double>(RAND_MAX))),
189            1.0f);
190           
191        material->setAmbient(osg::Material::FRONT_AND_BACK, color);
192        material->setDiffuse(osg::Material::FRONT_AND_BACK, color);
193        stateset->setAttributeAndModes(material, osg::StateAttribute::ON);
194
195        groups[i]->setStateSet(stateset);
196
197        if (UseImpostor)
198        {
199            osgSim::Impostor * impostor = new osgSim::Impostor();
200            impostor->setImpostorThreshold(static_cast<float> (Threshold));
201            impostor->addChild(groups[i]);
202            impostor->setRange(0, 0.0f, 1e7f);
203            impostor->setCenter(groups[i]->getBound().center());
204            Root->addChild(impostor);
205        }
206        else
207        {
208            Root->addChild(groups[i]);
209        }
210    }
211
212    delete[] groups;
213}
214
215
216int main( int argc, char **argv )
217{
218    // use an ArgumentParser object to manage the program arguments.
219    osg::ArgumentParser arguments(&argc,argv);
220
221    // construct the viewer.
222    osgViewer::Viewer viewer;
223
224    // add local test manipulator more suitable for testing impostors.
225    viewer.setCameraManipulator(new TestManipulator);
226
227
228    // load the nodes from the commandline arguments.
229    osg::Node* model = osgDB::readNodeFiles(arguments);
230    if (model)
231    {
232        // the osgSim::InsertImpostorsVisitor used lower down to insert impostors
233        // only operators on subclass of Group's, if the model top node is not
234        // a group then it won't be able to insert an impostor.  We therefore
235        // manually insert an impostor above the model.
236        if (dynamic_cast<osg::Group*>(model)==0)
237        {
238            const osg::BoundingSphere& bs = model->getBound();
239            if (bs.valid())
240            {
241
242                osgSim::Impostor* impostor = new osgSim::Impostor;
243
244                // standard LOD settings
245                impostor->addChild(model);
246                impostor->setRange(0,0.0f,1e7f);
247                impostor->setCenter(bs.center());
248
249                // impostor specfic settings.
250                impostor->setImpostorThresholdToBound(5.0f);
251
252                model = impostor;
253
254            }
255        }
256
257        // we insert an impostor node above the model, so we keep a handle
258        // on the rootnode of the model, the is required since the
259        // InsertImpostorsVisitor can add a new root in automatically and
260        // we would know about it, other than by following the parent path
261        // up from model.  This is really what should be done, but I'll pass
262        // on it right now as it requires a getRoots() method to be added to
263        // osg::Node, and we're about to make a release so no new features!
264        osg::Group* rootnode = new osg::Group;
265        rootnode->addChild(model);
266
267
268        // now insert impostors in the model using the InsertImpostorsVisitor.
269        osgSim::InsertImpostorsVisitor ov;
270
271        // traverse the model and collect all osg::Group's and osg::LOD's.
272        // however, don't traverse the rootnode since we want to keep it as
273        // the start of traversal, otherwise the insertImpostor could insert
274        // and Impostor above the current root, making it nolonger a root!
275        model->accept(ov);
276
277        // insert the Impostors above groups and LOD's
278        ov.insertImpostors();
279    }
280    else
281    {
282        // no user model so we'll create our own world.
283        model = Root = new osg::Group();
284        CreateHouses();
285        LayoutAsGrid();
286    }
287
288    // add model to viewer.
289    viewer.setSceneData(model);
290
291    return viewer.run();
292}
Note: See TracBrowser for help on using the browser.