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

Revision 6941, 8.9 kB (checked in by robert, 7 years ago)

From Martin Lavery and Robert Osfield, Updated examples to use a variation of the MIT License

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