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

Revision 7648, 10.4 kB (checked in by robert, 7 years ago)

From Roland Smeenk, "Attached you will find a large set of small typo fixes (mainly in the comments)."

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