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

Revision 11854, 13.3 kB (checked in by robert, 4 years ago)

Added command line options:

--tristripper
--no-tristripper
--smoother
--no-smoother

--remove-duplicate-vertices / --rdv
--optimize-vertex-cache / --ovc
--optimize-vertex-order / --ovo

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