root/OpenSceneGraph/trunk/examples/osgconv/osgconv.cpp @ 3174

Revision 3174, 13.5 kB (checked in by robert, 10 years ago)

Added support for compressing textures to osgconv, can be accessed by
running --compressed when outputting to a .ive file.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <stdio.h>
2
3#include <osg/ArgumentParser>
4#include <osg/ApplicationUsage>
5#include <osg/Group>
6#include <osg/Notify>
7#include <osg/Vec3>
8#include <osg/Geometry>
9#include <osg/Texture2D>
10
11#include <osgDB/Registry>
12#include <osgDB/ReadFile>
13#include <osgDB/WriteFile>
14#include <osgDB/FileNameUtils>
15#include <osgDB/ReaderWriter>
16
17#include <osgUtil/Optimizer>
18
19#include <osgProducer/Viewer>
20
21#include <iostream>
22
23#include "OrientationConverter.h"
24#include "GeoSet.h"
25
26typedef std::vector<std::string> FileNameList;
27
28
29////////////////////////////////////////////////////////////////////////////
30// Convert GeoSet To Geometry Visitor.
31////////////////////////////////////////////////////////////////////////////
32
33/** ConvertGeoSetsToGeometryVisitor all the old GeoSet Drawables to the new Geometry Drawables.*/
34class ConvertGeoSetsToGeometryVisitor : public osg::NodeVisitor
35{
36public:
37
38    ConvertGeoSetsToGeometryVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
39
40    virtual void apply(osg::Geode& geode)
41    {
42        for(unsigned int i=0;i<geode.getNumDrawables();++i)
43        {
44            osg::GeoSet* geoset = dynamic_cast<osg::GeoSet*>(geode.getDrawable(i));
45            if (geoset)
46            {
47                osg::Geometry* geom = geoset->convertToGeometry();
48                if (geom)
49                {
50                    osg::notify(osg::NOTICE)<<"Successfully converted GeoSet to Geometry"<<std::endl;
51                    geode.replaceDrawable(geoset,geom);
52                }
53                else
54                {
55                    osg::notify(osg::NOTICE)<<"*** Failed to convert GeoSet to Geometry"<<std::endl;
56                }
57
58            }
59        }
60    }
61
62    virtual void apply(osg::Node& node) { traverse(node); }
63
64};
65
66class GraphicsContext {
67    public:
68        GraphicsContext()
69        {
70            rs = new Producer::RenderSurface;
71            rs->setWindowRectangle(0,0,1,1);
72            rs->useBorder(false);
73            rs->useConfigEventThread(false);
74            rs->realize();
75            std::cout<<"Realized window"<<std::endl;
76        }
77
78        virtual ~GraphicsContext()
79        {
80        }
81       
82    private:
83        Producer::ref_ptr<Producer::RenderSurface> rs;
84};
85
86class CompressTexturesVisitor : public osg::NodeVisitor
87{
88public:
89
90    CompressTexturesVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
91
92    virtual void apply(osg::Node& node)
93    {
94        if (node.getStateSet()) apply(*node.getStateSet());
95        traverse(node);
96    }
97   
98    virtual void apply(osg::Geode& node)
99    {
100        if (node.getStateSet()) apply(*node.getStateSet());
101       
102        for(unsigned int i=0;i<node.getNumDrawables();++i)
103        {
104            osg::Drawable* drawable = node.getDrawable(i);
105            if (drawable && drawable->getStateSet()) apply(*drawable->getStateSet());
106        }
107       
108        traverse(node);
109    }
110   
111    virtual void apply(osg::StateSet& stateset)
112    {
113        // search for the existance of any texture object attributes
114        for(unsigned int i=0;i<stateset.getTextureAttributeList().size();++i)
115        {
116            osg::Texture2D* texture = dynamic_cast<osg::Texture2D*>(stateset.getTextureAttribute(i,osg::StateAttribute::TEXTURE));
117            if (texture)
118            {
119                _textureSet.insert(texture);
120            }
121        }
122    }
123   
124    void compress()
125    {
126        GraphicsContext context;
127
128        osg::ref_ptr<osg::State> state = new osg::State;
129
130        for(TextureSet::iterator itr=_textureSet.begin();
131            itr!=_textureSet.end();
132            ++itr)
133        {
134            osg::Texture2D* texture = const_cast<osg::Texture2D*>(itr->get());
135            osg::Image* image = texture->getImage();
136            if (image &&
137                (image->getPixelFormat()==GL_RGB || image->getPixelFormat()==GL_RGBA) &&
138                (image->s()>=32 && image->t()>=32))
139            {
140                texture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT3_COMPRESSION);
141
142                // get OpenGL driver to create texture from image.
143                texture->apply(*state);
144
145                image->readImageFromCurrentTexture(0,true);
146
147                texture->setInternalFormatMode(osg::Texture::USE_IMAGE_DATA_FORMAT);
148            }
149        }
150    }
151   
152    typedef std::set< osg::ref_ptr<osg::Texture2D> > TextureSet;
153    TextureSet _textureSet;
154   
155
156};
157
158
159static void usage( const char *prog, const char *msg )
160{
161    if (msg)
162    {
163        osg::notify(osg::NOTICE)<< std::endl;
164        osg::notify(osg::NOTICE) << msg << std::endl;
165    }
166    osg::notify(osg::NOTICE)<< std::endl;
167    osg::notify(osg::NOTICE)<<"usage:"<< std::endl;
168    osg::notify(osg::NOTICE)<<"    " << prog << " [options] infile1 [infile2 ...] outfile"<< std::endl;
169    osg::notify(osg::NOTICE)<< std::endl;
170    osg::notify(osg::NOTICE)<<"options:"<< std::endl;
171    osg::notify(osg::NOTICE)<<"    -O option          - ReaderWriter option"<< std::endl;
172    osg::notify(osg::NOTICE)<<"    --compress         - Compress textures."<< std::endl;
173    osg::notify(osg::NOTICE)<<"    -l libraryName     - load plugin of name libraryName"<< std::endl;
174    osg::notify(osg::NOTICE)<<"                         i.e. -l osgdb_pfb"<< std::endl;
175    osg::notify(osg::NOTICE)<<"                         Useful for loading reader/writers which can load"<< std::endl;
176    osg::notify(osg::NOTICE)<<"                         other file formats in addition to its extension."<< std::endl;
177    osg::notify(osg::NOTICE)<<"    -e extensionName   - load reader/wrter plugin for file extension"<< std::endl;
178    osg::notify(osg::NOTICE)<<"                         i.e. -e pfb"<< std::endl;
179    osg::notify(osg::NOTICE)<<"                         Useful short hand for specifying full library name as"<< std::endl;
180    osg::notify(osg::NOTICE)<<"                         done with -l above, as it automatically expands to the"<< std::endl;
181    osg::notify(osg::NOTICE)<<"                         full library name appropriate for each platform."<< std::endl;
182    osg::notify(osg::NOTICE)<<"    -o orientation     - Convert geometry from input files to output files."<< std::endl;
183    osg::notify(osg::NOTICE)<<
184                              "                         Format of orientation argument must be the following:\n"
185                              "\n"
186                              "                             X1,Y1,Z1-X2,Y2,Z2\n"
187                              "                         or\n"
188                              "                             degrees-A0,A1,A2\n"
189                              "\n"
190                              "                         where X1,Y1,Z1 represent the UP vector in the input\n"
191                              "                         files and X2,Y2,Z2 represent the UP vector of the\n"
192                              "                         output file, or degrees is the rotation angle in degrees\n"
193                              "                         around axis (A0,A1,A2).  For example, to convert a model\n"
194                              "                         built in a Y-Up coordinate system to a model with a Z-up\n"
195                              "                         coordinate system, the argument may look like\n"
196                              "\n"
197                              "                             0,1,0-0,0,1"
198                              "\n"
199                              "                          or\n"
200                              "                             -90-1,0,0\n"
201                              "\n" << std::endl;
202    osg::notify(osg::NOTICE)<<"    -t translation     - Convert spatial position of output files.  Format of\n"
203                              "                         translation argument must be the following :\n"
204                              "\n"
205                              "                             X,Y,Z\n"
206                              "\n"
207                              "                         where X, Y, and Z represent the coordinates of the\n"
208                              "                         absolute position in world space\n"
209                              << std::endl;
210    osg::notify(osg::NOTICE)<<"    -s scale           - Scale size of model.  Scale argument must be the \n"
211                              "                         following :\n"
212                              "\n"
213                              "                             SX,SY,SZ\n"
214                              "\n"
215                              "                         where SX, SY, and SZ represent the scale factors\n"
216                              "                         Caution: Scaling will be done in destination orientation\n"
217                              << std::endl;
218}
219
220
221int main( int argc, char **argv )
222{
223    // use an ArgumentParser object to manage the program arguments.
224    osg::ArgumentParser arguments(&argc,argv);
225   
226    // set up the usage document, in case we need to print out how to use this program.
227    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
228    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
229    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
230
231    // if user request help write it out to cout.
232    if (arguments.read("-h") || arguments.read("--help"))
233    {
234        usage( arguments.getApplicationName().c_str(), 0 );
235        //arguments.getApplicationUsage()->write(std::cout);
236        return 1;
237    }
238
239   
240    if (arguments.argc()<=1)
241    {
242        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
243        return 1;
244    }
245
246    FileNameList fileNames;
247    OrientationConverter oc;
248    bool do_convert = false;
249    bool compressTextures = false;
250
251    std::string str;
252    while (arguments.read("-O",str))
253    {
254        osgDB::ReaderWriter::Options* options = new osgDB::ReaderWriter::Options;
255        options->setOptionString(str);
256        osgDB::Registry::instance()->setOptions(options);
257    }
258
259    std::string ext;
260    while (arguments.read("-e",ext))
261    {
262        std::string libName = osgDB::Registry::instance()->createLibraryNameForExtension(ext);
263        osgDB::Registry::instance()->loadLibrary(libName);
264    }
265   
266    std::string libName;
267    while (arguments.read("-l",libName))
268    {
269        osgDB::Registry::instance()->loadLibrary(libName);
270    }
271
272    while (arguments.read("-t",str))
273    {
274        osg::Vec3 trans(0,0,0);
275        if( sscanf( str.c_str(), "%f,%f,%f",
276                &trans[0], &trans[1], &trans[2] ) != 3 )
277        {
278            usage( argv[0], "Translation argument format incorrect." );
279            return false;
280        }
281        oc.setTranslation( trans );
282        do_convert = true;
283    }
284
285    while (arguments.read("-o",str))
286    {
287        osg::Vec3 from, to;
288        if( sscanf( str.c_str(), "%f,%f,%f-%f,%f,%f",
289                &from[0], &from[1], &from[2],
290                &to[0], &to[1], &to[2]  )
291            != 6 )
292        {
293            float degrees;
294            osg::Vec3 axis;
295            // Try deg-axis format
296            if( sscanf( str.c_str(), "%f-%f,%f,%f",
297                    &degrees, &axis[0], &axis[1], &axis[2]  ) != 4 )
298            {
299                usage( argv[0], "Orientation argument format incorrect." );
300                return false;
301            }
302            else
303            {
304                oc.setRotation( degrees, axis );
305                do_convert = true;
306            }
307        }
308        else
309        {
310            oc.setRotation( from, to );
311            do_convert = true;
312        }
313
314    }   
315
316    while (arguments.read("--compressed"))
317    {
318        compressTextures = true;
319    }
320
321    // any option left unread are converted into errors to write out later.
322    arguments.reportRemainingOptionsAsUnrecognized();
323
324    // report any errors if they have occured when parsing the program aguments.
325    if (arguments.errors())
326    {
327        arguments.writeErrorMessages(std::cout);
328        return 1;
329    }
330
331    for(int pos=1;pos<arguments.argc();++pos)
332    {
333        if (!arguments.isOption(pos))
334        {
335            fileNames.push_back(arguments[pos]);
336        }
337    }
338
339
340    std::string fileNameOut("converted.osg");
341    if (fileNames.size()>1)
342    {
343        fileNameOut = fileNames.back();
344        fileNames.pop_back();
345    }
346
347    osg::ref_ptr<osg::Node> root = osgDB::readNodeFiles(fileNames);
348
349    if ( root.valid() )
350    {
351        // convert the old style GeoSet to Geometry
352        ConvertGeoSetsToGeometryVisitor cgtg;
353        if( root.valid() ) root->accept(cgtg);
354   
355        // optimize the scene graph, remove rendundent nodes and state etc.
356        osgUtil::Optimizer optimizer;
357        optimizer.optimize(root.get());
358       
359        if( do_convert )
360            root = oc.convert( root.get() );
361           
362        if (compressTextures)
363        {
364            std::string ext = osgDB::getFileExtension(fileNameOut);
365            if (ext=="ive")
366            {
367                CompressTexturesVisitor ctv;
368                root->accept(ctv);
369                ctv.compress();
370            }
371            else
372            {
373                std::cout<<"Warning: compressing texture only supported when outputing to .ive"<<std::endl;
374            }
375        }
376
377        if (osgDB::writeNodeFile(*root,fileNameOut))
378        {
379            osg::notify(osg::NOTICE)<<"Data written to '"<<fileNameOut<<"'."<< std::endl;
380        }
381    }
382    else
383    {
384        osg::notify(osg::NOTICE)<<"Error no data loaded."<< std::endl;
385        return 1;
386    }
387
388    return 0;
389}
Note: See TracBrowser for help on using the browser.