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

Revision 13497, 10.7 kB (checked in by robert, 9 days ago)

Fixed comment

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