root/OpenSceneGraph/trunk/examples/osgpagedlod/osgpagedlod.cpp @ 4385

Revision 4385, 7.9 kB (checked in by robert, 9 years ago)

Updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/Group>
2#include <osg/Notify>
3#include <osg/Geometry>
4#include <osg/ArgumentParser>
5#include <osg/ApplicationUsage>
6#include <osg/Texture2D>
7#include <osg/Geode>
8#include <osg/PagedLOD>
9
10#include <osgDB/Registry>
11#include <osgDB/ReadFile>
12#include <osgDB/WriteFile>
13#include <osgDB/FileNameUtils>
14
15#include <osgUtil/Optimizer>
16
17#include <iostream>
18#include <sstream>
19
20class NameVistor : public osg::NodeVisitor
21{
22public:
23    NameVistor():
24        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
25        _count(0)
26    {
27    }
28   
29    virtual void apply(osg::Node& node)
30    {
31        std::ostringstream os;
32        os << node.className() << "_"<<_count++;
33
34        node.setName(os.str());
35   
36        traverse(node);
37    }   
38   
39    unsigned int _count;
40};
41
42class CheckVisitor : public osg::NodeVisitor
43{
44public:
45    CheckVisitor():
46        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
47    {
48    }
49   
50    virtual void apply(osg::PagedLOD& plod)
51    {
52        std::cout<<"PagedLOD "<<plod.getName()<<"  numRanges = "<< plod.getNumRanges()<<"  numFiles = "<<plod.getNumFileNames()<<std::endl;
53        for(unsigned int i=0;i<plod.getNumFileNames();++i)
54        {
55            std::cout<<"  files = '"<<plod.getFileName(i)<<"'"<<std::endl;
56        }
57    }   
58};
59
60
61class WriteOutPagedLODSubgraphsVistor : public osg::NodeVisitor
62{
63public:
64    WriteOutPagedLODSubgraphsVistor():
65        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
66    {
67    }
68   
69    virtual void apply(osg::PagedLOD& plod)
70    {
71
72        // go through all the named children and write them out to disk.
73        for(unsigned int i=0;i<plod.getNumChildren();++i)
74        {
75            osg::Node* child = plod.getChild(i);
76            std::string filename = plod.getFileName(i);
77            if (!filename.empty())
78            {
79                osg::notify(osg::NOTICE)<<"Writing out "<<filename<<std::endl;
80                osgDB::writeNodeFile(*child,filename);
81            }
82        }
83   
84        traverse(plod);
85    }   
86};
87
88class ConvertToPageLODVistor : public osg::NodeVisitor
89{
90public:
91    ConvertToPageLODVistor(const std::string& basename, const std::string& extension, bool makeAllChildrenPaged):
92        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
93        _basename(basename),
94        _extension(extension),
95        _makeAllChildrenPaged(makeAllChildrenPaged)
96    {
97    }
98   
99    virtual ~ConvertToPageLODVistor()
100    {
101    }
102
103    virtual void apply(osg::LOD& lod)
104    {
105        _lodSet.insert(&lod);
106   
107        traverse(lod);
108    }   
109
110    virtual void apply(osg::PagedLOD& plod)
111    {
112        // do thing, but want to avoid call LOD.
113        traverse(plod);
114    }
115
116    void convert()
117    {
118        unsigned int lodNum = 0;
119        for(LODSet::iterator itr = _lodSet.begin();
120            itr != _lodSet.end();
121            ++itr, ++lodNum)
122        {
123            osg::ref_ptr<osg::LOD> lod = const_cast<osg::LOD*>(itr->get());
124           
125            if (lod->getNumParents()==0)
126            {
127                osg::notify(osg::NOTICE)<<"Warning can't operator on root node."<<std::endl;
128                break;
129            }
130
131            if (!_makeAllChildrenPaged && lod->getNumRanges()<2)
132            {
133                osg::notify(osg::NOTICE)<<"Leaving LOD with one child as is."<<std::endl;
134                break;
135            }
136
137            osg::notify(osg::NOTICE)<<"Converting LOD to PagedLOD."<<std::endl;
138           
139            osg::PagedLOD* plod = new osg::PagedLOD;
140           
141            const osg::LOD::RangeList& originalRangeList = lod->getRangeList();
142            typedef std::multimap< osg::LOD::MinMaxPair , unsigned int > MinMaxPairMap;
143            MinMaxPairMap rangeMap;
144            unsigned int pos = 0;
145            for(osg::LOD::RangeList::const_iterator ritr = originalRangeList.begin();
146                ritr != originalRangeList.end();
147                ++ritr, ++pos)
148            {
149                rangeMap.insert(std::multimap< osg::LOD::MinMaxPair , unsigned int >::value_type(*ritr, pos));
150            }
151           
152            pos = 0;
153            for(MinMaxPairMap::reverse_iterator mitr = rangeMap.rbegin();
154                mitr != rangeMap.rend();
155                ++mitr, ++pos)
156            {
157                if (pos==0 && !_makeAllChildrenPaged)
158                {
159                    plod->addChild(lod->getChild(mitr->second), mitr->first.first, mitr->first.second);
160                }
161                else
162                {
163                    std::string filename = _basename;
164                    std::ostringstream os;
165                    os << _basename << "_"<<lodNum<<"_"<<pos<<_extension;
166                   
167                    plod->addChild(lod->getChild(mitr->second), mitr->first.first, mitr->first.second, os.str());
168                }
169            }
170           
171            osg::Node::ParentList parents = lod->getParents();
172            for(osg::Node::ParentList::iterator pitr=parents.begin();
173                pitr!=parents.end();
174                ++pitr)
175            {
176                (*pitr)->replaceChild(lod.get(),plod);
177            }
178
179            plod->setCenter(plod->getBound().center());
180           
181
182        }
183    }
184
185   
186    typedef std::set< osg::ref_ptr<osg::LOD> >  LODSet;
187    LODSet _lodSet;
188    std::string _basename;
189    std::string _extension;
190    bool _makeAllChildrenPaged;
191};
192
193
194int main( int argc, char **argv )
195{
196
197    // use an ArgumentParser object to manage the program arguments.
198    osg::ArgumentParser arguments(&argc,argv);
199   
200    // set up the usage document, in case we need to print out how to use this program.
201    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
202    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" creates a hierachy of files for paging which can be later loaded by viewers.");
203    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
204    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
205    arguments.getApplicationUsage()->addCommandLineOption("-o","set the output file (defaults to output.ive)");
206    arguments.getApplicationUsage()->addCommandLineOption("--makeAllChildrenPaged","Force all children of LOD to be written out as external PagedLOD children");
207
208    // if user request help write it out to cout.
209    if (arguments.read("-h") || arguments.read("--help"))
210    {
211        arguments.getApplicationUsage()->write(std::cout);
212        return 1;
213    }
214
215    std::string outputfile("output.ive");
216    while (arguments.read("-o",outputfile)) {}
217   
218   
219    bool makeAllChildrenPaged = false;
220    while (arguments.read("--makeAllChildrenPaged")) { makeAllChildrenPaged = true; }
221
222    // any option left unread are converted into errors to write out later.
223    arguments.reportRemainingOptionsAsUnrecognized();
224
225    // report any errors if they have occured when parsing the program aguments.
226    if (arguments.errors())
227    {
228        arguments.writeErrorMessages(std::cout);
229        return 1;
230    }
231   
232//     if (arguments.argc()<=1)
233//     {
234//         arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
235//         return 1;
236//     }
237
238
239    osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
240   
241    if (!model)
242    {
243        osg::notify(osg::NOTICE)<<"No model loaded."<<std::endl;
244        return 1;
245    }
246   
247    std::string basename( osgDB::getNameLessExtension(outputfile) );
248    std::string ext = '.'+ osgDB::getFileExtension(outputfile);
249   
250    ConvertToPageLODVistor converter(basename,ext, makeAllChildrenPaged);
251    model->accept(converter);
252    converter.convert();
253   
254    NameVistor nameNodes;
255    model->accept(nameNodes);
256
257    //CheckVisitor checkNodes;
258    //model->accept(checkNodes);
259
260    if (model.valid())
261    {
262        osgDB::writeNodeFile(*model,outputfile);
263       
264        WriteOutPagedLODSubgraphsVistor woplsv;
265        model->accept(woplsv);
266    }
267
268    return 0;
269}
Note: See TracBrowser for help on using the browser.