root/OpenSceneGraph/trunk/examples/osganalysis/osganalysis.cpp @ 11849

Revision 11849, 13.7 kB (checked in by robert, 4 years ago)

Added support for enable VBO's and doing simplification.

Line 
1/* OpenSceneGraph example, osgterrain.
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
20#include <osgViewer/Viewer>
21#include <osgViewer/ViewerEventHandlers>
22
23#include <osgDB/ReadFile>
24
25#include <osgGA/TrackballManipulator>
26
27#include <osgUtil/IncrementalCompileOperation>
28#include <osgUtil/Simplifier>
29
30class StripStateVisitor : public osg::NodeVisitor
31{
32public:
33    StripStateVisitor(bool useStateSets, bool useDisplayLists, bool useVBO):
34        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
35        _useStateSets(useStateSets),
36        _useDisplayLists(useDisplayLists),
37        _useVBO(useVBO) {}
38
39    bool _useStateSets;
40    bool _useDisplayLists;
41    bool _useVBO;
42
43    void apply(osg::Node& node)
44    {
45        if (!_useStateSets && node.getStateSet()) node.setStateSet(0);
46        traverse(node);
47    }
48
49    void apply(osg::Geode& node)
50    {
51        if (!_useStateSets && node.getStateSet()) node.setStateSet(0);
52        for(unsigned int i = 0; i<node.getNumDrawables(); ++i)
53        {
54            process(*node.getDrawable(i));
55        }
56
57        traverse(node);
58    }
59
60    void process(osg::Drawable& drawable)
61    {
62        if (!_useStateSets && drawable.getStateSet())
63        {
64            drawable.setStateSet(0);
65        }
66
67        drawable.setUseDisplayList(_useDisplayLists);
68        drawable.setUseVertexBufferObjects(_useVBO);
69    }
70};
71
72class SceneGraphProcessor : public osg::Referenced
73{
74public:
75    SceneGraphProcessor()
76    {
77        _init();
78    }
79
80    SceneGraphProcessor(osg::ArgumentParser& arguments)
81    {
82        _init();
83
84        while (arguments.read("--vbo")) { modifyDrawableSettings = true; useVBO = true;  }
85        while (arguments.read("--dl")) { modifyDrawableSettings = true; useDisplayLists = true;  }
86
87        while (arguments.read("-s", simplificatioRatio)) {}
88
89        while (arguments.read("--build-mipmaps")) { modifyTextureSettings = true; buildImageMipmaps = true; }
90        while (arguments.read("--compress")) { modifyTextureSettings = true; compressImages = true; }
91        while (arguments.read("--disable-mipmaps")) { modifyTextureSettings = true; disableMipmaps = true; }
92
93        OSG_NOTICE<<"simplificatioRatio="<<simplificatioRatio<<std::endl;
94    }
95
96    virtual osg::Node* process(osg::Node* node)
97    {
98        if (!node)
99        {
100            OSG_NOTICE<<"SceneGraphProcessor::process(Node*) : error cannot process NULL Node."<<std::endl;
101            return 0;
102        }
103
104        OSG_NOTICE<<"SceneGraphProcessor::process("<<node<<") : "<<node->getName()<<std::endl;
105
106        if (simplificatioRatio < 1.0)
107        {
108            OSG_NOTICE<<"Running simplifier with simplification ratio="<<simplificatioRatio<<std::endl;
109            float maxError = 4.0f;
110            osgUtil::Simplifier simplifier(simplificatioRatio, maxError);
111            node->accept(simplifier);
112        }
113
114        if (modifyDrawableSettings || modifyTextureSettings)
115        {
116            OSG_NOTICE<<"Running StripStateVisitor"<<std::endl;
117            StripStateVisitor ssv(true, useDisplayLists, useVBO);
118            node->accept(ssv);
119        }
120
121
122        return node;
123    }
124
125protected:
126
127    void _init()
128    {
129        modifyDrawableSettings = false;
130        useVBO = false;
131        useDisplayLists = false;
132        simplificatioRatio = 1.0;
133
134        modifyTextureSettings = false;
135        buildImageMipmaps = false;
136        compressImages = false;
137        disableMipmaps = false;
138    }
139
140    bool modifyDrawableSettings;
141    bool useVBO;
142    bool useDisplayLists;
143    float simplificatioRatio;
144
145    bool modifyTextureSettings;
146    bool buildImageMipmaps;
147    bool compressImages;
148    bool disableMipmaps;
149
150};
151
152
153class CustomCompileCompletedCallback : public osgUtil::IncrementalCompileOperation::CompileCompletedCallback
154{
155public:
156    CustomCompileCompletedCallback():
157        completed(false) {}
158
159    virtual bool compileCompleted(osgUtil::IncrementalCompileOperation::CompileSet* compileSet)
160    {
161        OSG_NOTICE<<"compileCompleted"<<std::endl;
162        completed = true;
163        return true;
164    }
165
166    bool completed;
167};
168
169class DatabasePagingOperation : public osg::Operation, public osgUtil::IncrementalCompileOperation::CompileCompletedCallback
170{
171public:
172
173    DatabasePagingOperation(const std::string& filename,
174                             SceneGraphProcessor* sceneGraphProcessor,
175                             osgUtil::IncrementalCompileOperation* ico):
176        Operation("DatabasePaging Operation", false),
177        _filename(filename),
178        _modelReadyToMerge(false),
179        _sceneGraphProcessor(sceneGraphProcessor),
180        _incrementalCompileOperation(ico) {}
181
182    virtual void operator () (osg::Object* object)
183    {
184        osg::notify(osg::NOTICE)<<"LoadAndCompileOperation "<<_filename<<std::endl;
185
186        _modelReadyToMerge = false;
187        _loadedModel = osgDB::readNodeFile(_filename);
188
189        if (_loadedModel.valid())
190        {
191            if (_sceneGraphProcessor.valid())
192            {
193                _loadedModel = _sceneGraphProcessor->process(_loadedModel.get());
194            }
195        }
196
197        if (_loadedModel.valid())
198        {
199            if (_incrementalCompileOperation.valid())
200            {
201                osg::ref_ptr<osgUtil::IncrementalCompileOperation::CompileSet> compileSet =
202                    new osgUtil::IncrementalCompileOperation::CompileSet(_loadedModel.get());
203
204                compileSet->_compileCompletedCallback = this;
205
206                _incrementalCompileOperation->add(compileSet.get());
207            }
208            else
209            {
210                _modelReadyToMerge = true;
211            }
212        }
213
214        osg::notify(osg::NOTICE)<<"done LoadAndCompileOperation "<<_filename<<std::endl;
215    }
216
217    virtual bool compileCompleted(osgUtil::IncrementalCompileOperation::CompileSet* compileSet)
218    {
219        OSG_NOTICE<<"compileCompleted"<<std::endl;
220        _modelReadyToMerge = true;
221        return true;
222    }
223
224    std::string                                         _filename;
225    osg::ref_ptr<osg::Node>                             _loadedModel;
226    bool                                                _modelReadyToMerge;
227    osg::ref_ptr<SceneGraphProcessor>                   _sceneGraphProcessor;
228    osg::ref_ptr<osgUtil::IncrementalCompileOperation>  _incrementalCompileOperation;
229};
230
231
232int main(int argc, char** argv)
233{
234    osg::ArgumentParser arguments(&argc, argv);
235
236    // construct the viewer.
237    osgViewer::Viewer viewer(arguments);
238
239    viewer.setCameraManipulator(new osgGA::TrackballManipulator());
240    viewer.addEventHandler(new osgViewer::StatsHandler());
241    viewer.addEventHandler(new osgViewer::WindowSizeHandler);
242
243    /////////////////////////////////////////////////////////////////////////////////
244    //
245    // IncrementalCompileOperation settings
246    //
247    osg::ref_ptr<osgUtil::IncrementalCompileOperation> incrementalCompile = new osgUtil::IncrementalCompileOperation;
248    viewer.setIncrementalCompileOperation(incrementalCompile.get());
249
250    if (arguments.read("--force") || arguments.read("-f"))
251    {
252        incrementalCompile->assignForceTextureDownloadGeometry();
253    }
254
255    if (arguments.read("-a"))
256    {
257        incrementalCompile->setMinimumTimeAvailableForGLCompileAndDeletePerFrame(1);
258        incrementalCompile->setConservativeTimeRatio(1);
259        incrementalCompile->setMaximumNumOfObjectsToCompilePerFrame(100);
260    }
261    else if (arguments.read("-c"))
262    {
263        incrementalCompile->setMinimumTimeAvailableForGLCompileAndDeletePerFrame(0.0001);
264        incrementalCompile->setConservativeTimeRatio(0.01);
265        incrementalCompile->setMaximumNumOfObjectsToCompilePerFrame(1);
266    }
267
268    /////////////////////////////////////////////////////////////////////////////////
269    //
270    // SceneGraph processing setup
271    //
272    osg::ref_ptr<SceneGraphProcessor> sceneGraphProcessor = new SceneGraphProcessor(arguments);
273
274    /////////////////////////////////////////////////////////////////////////////////
275    //
276    // Database settings
277    //
278    double timeBetweenMerges = 2.0;
279    while(arguments.read("--interval",timeBetweenMerges)) {}
280
281    bool readDatabasesInPagingThread = false;
282    while(arguments.read("--paging")) { readDatabasesInPagingThread = true; }
283
284    typedef std::vector< std::string > FileNames;
285    FileNames fileNames;
286    for(int pos=1;pos<arguments.argc();++pos)
287    {
288        if (!arguments.isOption(pos))
289        {
290            fileNames.push_back(arguments[pos]);
291        }
292    }
293
294    if (fileNames.empty())
295    {
296        OSG_NOTICE<<"No files loaded, please specifies files on commandline."<<std::endl;
297        return 1;
298    }
299
300
301    if (readDatabasesInPagingThread)
302    {
303        // load the models using a paging thread and use the incremental compile operation to
304        // manage the compilation of GL objects without breaking frame.
305
306        unsigned int modelIndex = 0;
307
308        osg::ref_ptr<osg::OperationThread> databasePagingThread;
309        osg::ref_ptr<DatabasePagingOperation> databasePagingOperation;
310
311        databasePagingThread = new osg::OperationThread;
312        databasePagingThread->startThread();
313
314        databasePagingOperation = new DatabasePagingOperation(
315            fileNames[modelIndex++],
316            sceneGraphProcessor.get(),
317            incrementalCompile.get());
318
319        databasePagingThread->add(databasePagingOperation.get());
320
321        osg::ref_ptr<osg::Group> group = new osg::Group;
322        viewer.setSceneData(group);
323
324        viewer.realize();
325
326        double timeOfLastMerge = viewer.getFrameStamp()->getReferenceTime();
327
328        while(!viewer.done())
329        {
330            viewer.frame();
331
332            double currentTime = viewer.getFrameStamp()->getReferenceTime();
333
334            if (!databasePagingOperation &&
335                modelIndex<fileNames.size() &&
336                (currentTime-timeOfLastMerge)>timeBetweenMerges)
337            {
338                databasePagingOperation = new DatabasePagingOperation(
339                    fileNames[modelIndex++],
340                    sceneGraphProcessor.get(),
341                    incrementalCompile.get());
342
343                databasePagingThread->add(databasePagingOperation.get());
344            }
345
346            if (databasePagingOperation.get() && databasePagingOperation->_modelReadyToMerge)
347            {
348                timeOfLastMerge = currentTime;
349
350                group->removeChildren(0,group->getNumChildren());
351
352                group->addChild(databasePagingOperation->_loadedModel.get());
353
354                viewer.home();
355
356                // we no longer need the paging operation as it's done it's job.
357                databasePagingOperation = 0;
358
359                viewer.home();
360            }
361        }
362
363    }
364    else
365    {
366        // load the models directly and then just use the IncrementalCompileOperation to
367        // compile the GL objects for us.
368        typedef std::vector< osg::ref_ptr<osg::Node> > Models;
369        Models models;
370        unsigned int modelIndex = 0;
371
372        for(FileNames::iterator itr = fileNames.begin();
373            itr != fileNames.end();
374            ++itr)
375        {
376            // not an option so assume string is a filename.
377            osg::ref_ptr<osg::Node> node = osgDB::readNodeFile( *itr );
378            if(node.valid())
379            {
380                if (node->getName().empty()) node->setName( *itr );
381
382                node = sceneGraphProcessor->process(node.get());
383
384                models.push_back(node.get());
385            }
386        }
387
388        osg::ref_ptr<osg::Group> group = new osg::Group;
389        group->addChild(models[modelIndex++].get());
390
391        viewer.setSceneData(group);
392
393        viewer.realize();
394
395        double timeOfLastMerge = viewer.getFrameStamp()->getReferenceTime();
396
397        osg::ref_ptr<CustomCompileCompletedCallback> compileCompletedCallback;
398
399        while(!viewer.done())
400        {
401            viewer.frame();
402
403            double currentTime = viewer.getFrameStamp()->getReferenceTime();
404
405            if (!compileCompletedCallback &&
406                modelIndex<fileNames.size() &&
407                (currentTime-timeOfLastMerge)>timeBetweenMerges)
408            {
409                OSG_NOTICE<<"Compiling model "<<modelIndex<<" at "<<currentTime<<std::endl;
410
411                osg::ref_ptr<osgUtil::IncrementalCompileOperation::CompileSet> compileSet =
412                    new osgUtil::IncrementalCompileOperation::CompileSet(models[modelIndex].get());
413
414                compileCompletedCallback = new CustomCompileCompletedCallback;
415
416                compileSet->_compileCompletedCallback = compileCompletedCallback;
417
418                incrementalCompile->add(compileSet.get());
419            }
420
421            if (compileCompletedCallback.valid() && compileCompletedCallback->completed)
422            {
423                OSG_NOTICE<<"Merging model "<<modelIndex<<" at "<<currentTime<<std::endl;
424
425                timeOfLastMerge = currentTime;
426
427                group->removeChildren(0,group->getNumChildren());
428
429                group->addChild(models[modelIndex++].get());
430
431                compileCompletedCallback = 0;
432
433                viewer.home();
434            }
435        }
436    }
437
438    return 0;
439}
Note: See TracBrowser for help on using the browser.