2003-02-21 22:05:39 +08:00
# include <stdio.h>
2004-07-22 19:59:58 +08:00
# include <osg/ArgumentParser>
# include <osg/ApplicationUsage>
2003-02-21 22:05:39 +08:00
# include <osg/Group>
# include <osg/Notify>
# include <osg/Vec3>
2003-05-21 20:15:45 +08:00
# include <osg/Geometry>
2004-07-22 19:59:58 +08:00
# include <osg/Texture2D>
2003-02-21 22:05:39 +08:00
# include <osgDB/Registry>
# include <osgDB/ReadFile>
# include <osgDB/WriteFile>
2004-07-22 20:10:53 +08:00
# include <osgDB/FileNameUtils>
2003-02-21 22:05:39 +08:00
# include <osgDB/ReaderWriter>
2003-06-24 23:40:09 +08:00
# include <osgUtil/Optimizer>
2004-07-22 19:59:58 +08:00
# include <osgProducer/Viewer>
# include <iostream>
2003-02-21 22:05:39 +08:00
# include "OrientationConverter.h"
2003-05-21 20:15:45 +08:00
# include "GeoSet.h"
2003-02-21 22:05:39 +08:00
typedef std : : vector < std : : string > FileNameList ;
2003-05-21 20:15:45 +08:00
////////////////////////////////////////////////////////////////////////////
// Convert GeoSet To Geometry Visitor.
////////////////////////////////////////////////////////////////////////////
/** ConvertGeoSetsToGeometryVisitor all the old GeoSet Drawables to the new Geometry Drawables.*/
class ConvertGeoSetsToGeometryVisitor : public osg : : NodeVisitor
{
public :
ConvertGeoSetsToGeometryVisitor ( ) : osg : : NodeVisitor ( osg : : NodeVisitor : : TRAVERSE_ALL_CHILDREN ) { }
virtual void apply ( osg : : Geode & geode )
{
for ( unsigned int i = 0 ; i < geode . getNumDrawables ( ) ; + + i )
{
osg : : GeoSet * geoset = dynamic_cast < osg : : GeoSet * > ( geode . getDrawable ( i ) ) ;
if ( geoset )
{
osg : : Geometry * geom = geoset - > convertToGeometry ( ) ;
if ( geom )
{
2004-03-03 21:27:21 +08:00
osg : : notify ( osg : : NOTICE ) < < " Successfully converted GeoSet to Geometry " < < std : : endl ;
2003-05-21 20:15:45 +08:00
geode . replaceDrawable ( geoset , geom ) ;
}
else
{
2004-03-03 21:27:21 +08:00
osg : : notify ( osg : : NOTICE ) < < " *** Failed to convert GeoSet to Geometry " < < std : : endl ;
2003-05-21 20:15:45 +08:00
}
}
}
}
virtual void apply ( osg : : Node & node ) { traverse ( node ) ; }
} ;
2003-02-21 22:05:39 +08:00
2004-07-22 19:59:58 +08:00
class GraphicsContext {
public :
GraphicsContext ( )
{
rs = new Producer : : RenderSurface ;
rs - > setWindowRectangle ( 0 , 0 , 1 , 1 ) ;
rs - > useBorder ( false ) ;
rs - > useConfigEventThread ( false ) ;
rs - > realize ( ) ;
std : : cout < < " Realized window " < < std : : endl ;
}
virtual ~ GraphicsContext ( )
{
}
private :
Producer : : ref_ptr < Producer : : RenderSurface > rs ;
} ;
class CompressTexturesVisitor : public osg : : NodeVisitor
{
public :
CompressTexturesVisitor ( ) : osg : : NodeVisitor ( osg : : NodeVisitor : : TRAVERSE_ALL_CHILDREN ) { }
virtual void apply ( osg : : Node & node )
{
if ( node . getStateSet ( ) ) apply ( * node . getStateSet ( ) ) ;
traverse ( node ) ;
}
virtual void apply ( osg : : Geode & node )
{
if ( node . getStateSet ( ) ) apply ( * node . getStateSet ( ) ) ;
for ( unsigned int i = 0 ; i < node . getNumDrawables ( ) ; + + i )
{
osg : : Drawable * drawable = node . getDrawable ( i ) ;
if ( drawable & & drawable - > getStateSet ( ) ) apply ( * drawable - > getStateSet ( ) ) ;
}
traverse ( node ) ;
}
virtual void apply ( osg : : StateSet & stateset )
{
// search for the existance of any texture object attributes
for ( unsigned int i = 0 ; i < stateset . getTextureAttributeList ( ) . size ( ) ; + + i )
{
osg : : Texture2D * texture = dynamic_cast < osg : : Texture2D * > ( stateset . getTextureAttribute ( i , osg : : StateAttribute : : TEXTURE ) ) ;
if ( texture )
{
_textureSet . insert ( texture ) ;
}
}
}
void compress ( )
{
GraphicsContext context ;
osg : : ref_ptr < osg : : State > state = new osg : : State ;
for ( TextureSet : : iterator itr = _textureSet . begin ( ) ;
itr ! = _textureSet . end ( ) ;
+ + itr )
{
osg : : Texture2D * texture = const_cast < osg : : Texture2D * > ( itr - > get ( ) ) ;
osg : : Image * image = texture - > getImage ( ) ;
if ( image & &
( image - > getPixelFormat ( ) = = GL_RGB | | image - > getPixelFormat ( ) = = GL_RGBA ) & &
( image - > s ( ) > = 32 & & image - > t ( ) > = 32 ) )
{
texture - > setInternalFormatMode ( osg : : Texture : : USE_S3TC_DXT3_COMPRESSION ) ;
// get OpenGL driver to create texture from image.
texture - > apply ( * state ) ;
image - > readImageFromCurrentTexture ( 0 , true ) ;
texture - > setInternalFormatMode ( osg : : Texture : : USE_IMAGE_DATA_FORMAT ) ;
}
}
}
typedef std : : set < osg : : ref_ptr < osg : : Texture2D > > TextureSet ;
TextureSet _textureSet ;
} ;
2003-02-21 22:05:39 +08:00
static void usage ( const char * prog , const char * msg )
{
2004-07-22 19:59:58 +08:00
if ( msg )
{
osg : : notify ( osg : : NOTICE ) < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < msg < < std : : endl ;
}
2003-02-21 22:05:39 +08:00
osg : : notify ( osg : : NOTICE ) < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " usage: " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " " < < prog < < " [options] infile1 [infile2 ...] outfile " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " options: " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " -O option - ReaderWriter option " < < std : : endl ;
2004-07-22 19:59:58 +08:00
osg : : notify ( osg : : NOTICE ) < < " --compress - Compress textures. " < < std : : endl ;
2003-02-21 22:05:39 +08:00
osg : : notify ( osg : : NOTICE ) < < " -l libraryName - load plugin of name libraryName " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " i.e. -l osgdb_pfb " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " Useful for loading reader/writers which can load " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " other file formats in addition to its extension. " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " -e extensionName - load reader/wrter plugin for file extension " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " i.e. -e pfb " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " Useful short hand for specifying full library name as " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " done with -l above, as it automatically expands to the " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " full library name appropriate for each platform. " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " -o orientation - Convert geometry from input files to output files. " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < <
" Format of orientation argument must be the following: \n "
2004-05-17 10:48:53 +08:00
" \n "
2003-02-21 22:05:39 +08:00
" X1,Y1,Z1-X2,Y2,Z2 \n "
2004-05-17 10:48:53 +08:00
" or \n "
" degrees-A0,A1,A2 \n "
" \n "
2003-02-21 22:05:39 +08:00
" where X1,Y1,Z1 represent the UP vector in the input \n "
2004-05-17 10:48:53 +08:00
" files and X2,Y2,Z2 represent the UP vector of the \n "
" output file, or degrees is the rotation angle in degrees \n "
" around axis (A0,A1,A2). For example, to convert a model \n "
" built in a Y-Up coordinate system to a model with a Z-up \n "
" coordinate system, the argument may look like \n "
" \n "
" 0,1,0-0,0,1 "
" \n "
" or \n "
" -90-1,0,0 \n "
" \n " < < std : : endl ;
2003-02-21 22:05:39 +08:00
osg : : notify ( osg : : NOTICE ) < < " -t translation - Convert spatial position of output files. Format of \n "
" translation argument must be the following : \n "
2004-05-17 10:48:53 +08:00
" \n "
" X,Y,Z \n "
" \n "
" where X, Y, and Z represent the coordinates of the \n "
" absolute position in world space \n "
< < std : : endl ;
2003-02-21 22:05:39 +08:00
osg : : notify ( osg : : NOTICE ) < < " -s scale - Scale size of model. Scale argument must be the \n "
" following : \n "
2004-05-17 10:48:53 +08:00
" \n "
" SX,SY,SZ \n "
" \n "
" where SX, SY, and SZ represent the scale factors \n "
" Caution: Scaling will be done in destination orientation \n "
< < std : : endl ;
2003-02-21 22:05:39 +08:00
}
2004-07-22 19:59:58 +08:00
int main ( int argc , char * * argv )
2003-02-21 22:05:39 +08:00
{
2004-07-22 19:59:58 +08:00
// use an ArgumentParser object to manage the program arguments.
osg : : ArgumentParser arguments ( & argc , argv ) ;
// set up the usage document, in case we need to print out how to use this program.
arguments . getApplicationUsage ( ) - > setApplicationName ( arguments . getApplicationName ( ) ) ;
arguments . getApplicationUsage ( ) - > setDescription ( arguments . getApplicationName ( ) + " is the standard OpenSceneGraph example which loads and visualises 3d models. " ) ;
arguments . getApplicationUsage ( ) - > setCommandLineUsage ( arguments . getApplicationName ( ) + " [options] filename ... " ) ;
// if user request help write it out to cout.
if ( arguments . read ( " -h " ) | | arguments . read ( " --help " ) )
{
usage ( arguments . getApplicationName ( ) . c_str ( ) , 0 ) ;
//arguments.getApplicationUsage()->write(std::cout);
return 1 ;
}
2003-02-21 22:05:39 +08:00
2004-07-22 19:59:58 +08:00
if ( arguments . argc ( ) < = 1 )
2003-02-21 22:05:39 +08:00
{
2004-07-22 19:59:58 +08:00
arguments . getApplicationUsage ( ) - > write ( std : : cout , osg : : ApplicationUsage : : COMMAND_LINE_OPTION ) ;
return 1 ;
}
FileNameList fileNames ;
OrientationConverter oc ;
bool do_convert = false ;
bool compressTextures = false ;
2003-02-21 22:05:39 +08:00
2004-07-22 19:59:58 +08:00
std : : string str ;
while ( arguments . read ( " -O " , str ) )
{
osgDB : : ReaderWriter : : Options * options = new osgDB : : ReaderWriter : : Options ;
options - > setOptionString ( str ) ;
osgDB : : Registry : : instance ( ) - > setOptions ( options ) ;
}
std : : string ext ;
while ( arguments . read ( " -e " , ext ) )
{
std : : string libName = osgDB : : Registry : : instance ( ) - > createLibraryNameForExtension ( ext ) ;
osgDB : : Registry : : instance ( ) - > loadLibrary ( libName ) ;
}
std : : string libName ;
while ( arguments . read ( " -l " , libName ) )
{
osgDB : : Registry : : instance ( ) - > loadLibrary ( libName ) ;
}
2004-08-22 01:29:19 +08:00
#if 0
if ( nexti < argc )
{
osg : : Vec3 scale ( 0 , 0 , 0 ) ;
if ( sscanf ( argv [ nexti + + ] , " %f,%f,%f " ,
& scale [ 0 ] , & scale [ 1 ] , & scale [ 2 ] ) ! = 3 )
{
usage ( argv [ 0 ] , " Scale argument format incorrect. " ) ;
return false ;
}
oc . setScale ( scale ) ;
do_convert = true ;
}
else
{
usage ( argv [ 0 ] , " Scale conversion option requires an argument. " ) ;
return false ;
}
break ;
# endif
2004-07-22 19:59:58 +08:00
while ( arguments . read ( " -o " , str ) )
{
osg : : Vec3 from , to ;
if ( sscanf ( str . c_str ( ) , " %f,%f,%f-%f,%f,%f " ,
& from [ 0 ] , & from [ 1 ] , & from [ 2 ] ,
& to [ 0 ] , & to [ 1 ] , & to [ 2 ] )
! = 6 )
{
float degrees ;
osg : : Vec3 axis ;
// Try deg-axis format
if ( sscanf ( str . c_str ( ) , " %f-%f,%f,%f " ,
& degrees , & axis [ 0 ] , & axis [ 1 ] , & axis [ 2 ] ) ! = 4 )
2004-05-17 10:48:53 +08:00
{
2004-07-22 19:59:58 +08:00
usage ( argv [ 0 ] , " Orientation argument format incorrect. " ) ;
2004-08-22 01:29:19 +08:00
return 1 ;
2004-07-22 19:59:58 +08:00
}
else
{
oc . setRotation ( degrees , axis ) ;
do_convert = true ;
2004-05-17 10:48:53 +08:00
}
2004-07-22 19:59:58 +08:00
}
else
2003-02-21 22:05:39 +08:00
{
2004-07-22 19:59:58 +08:00
oc . setRotation ( from , to ) ;
do_convert = true ;
2003-02-21 22:05:39 +08:00
}
2004-07-22 19:59:58 +08:00
}
2004-08-22 01:29:19 +08:00
while ( arguments . read ( " -s " , str ) )
{
osg : : Vec3 scale ( 0 , 0 , 0 ) ;
if ( sscanf ( str . c_str ( ) , " %f,%f,%f " ,
& scale [ 0 ] , & scale [ 1 ] , & scale [ 2 ] ) ! = 3 )
{
usage ( argv [ 0 ] , " Scale argument format incorrect. " ) ;
return 1 ;
}
oc . setScale ( scale ) ;
do_convert = true ;
}
while ( arguments . read ( " -t " , str ) )
{
osg : : Vec3 trans ( 0 , 0 , 0 ) ;
if ( sscanf ( str . c_str ( ) , " %f,%f,%f " ,
& trans [ 0 ] , & trans [ 1 ] , & trans [ 2 ] ) ! = 3 )
{
usage ( argv [ 0 ] , " Translation argument format incorrect. " ) ;
return 1 ;
}
oc . setTranslation ( trans ) ;
do_convert = true ;
}
2004-07-22 19:59:58 +08:00
while ( arguments . read ( " --compressed " ) )
2003-02-21 22:05:39 +08:00
{
2004-07-22 19:59:58 +08:00
compressTextures = true ;
2003-02-21 22:05:39 +08:00
}
2004-07-22 19:59:58 +08:00
// any option left unread are converted into errors to write out later.
arguments . reportRemainingOptionsAsUnrecognized ( ) ;
2003-02-21 22:05:39 +08:00
2004-07-22 19:59:58 +08:00
// report any errors if they have occured when parsing the program aguments.
if ( arguments . errors ( ) )
{
arguments . writeErrorMessages ( std : : cout ) ;
return 1 ;
}
2003-02-21 22:05:39 +08:00
2004-07-22 19:59:58 +08:00
for ( int pos = 1 ; pos < arguments . argc ( ) ; + + pos )
{
if ( ! arguments . isOption ( pos ) )
{
fileNames . push_back ( arguments [ pos ] ) ;
}
}
2003-02-21 22:05:39 +08:00
std : : string fileNameOut ( " converted.osg " ) ;
if ( fileNames . size ( ) > 1 )
{
fileNameOut = fileNames . back ( ) ;
fileNames . pop_back ( ) ;
}
osg : : ref_ptr < osg : : Node > root = osgDB : : readNodeFiles ( fileNames ) ;
2003-05-21 20:15:45 +08:00
2004-06-28 17:05:33 +08:00
if ( root . valid ( ) )
{
// convert the old style GeoSet to Geometry
ConvertGeoSetsToGeometryVisitor cgtg ;
if ( root . valid ( ) ) root - > accept ( cgtg ) ;
2003-06-24 23:40:09 +08:00
2004-06-28 17:05:33 +08:00
// optimize the scene graph, remove rendundent nodes and state etc.
osgUtil : : Optimizer optimizer ;
optimizer . optimize ( root . get ( ) ) ;
if ( do_convert )
root = oc . convert ( root . get ( ) ) ;
2004-07-22 19:59:58 +08:00
if ( compressTextures )
{
2004-07-22 20:10:53 +08:00
std : : string ext = osgDB : : getFileExtension ( fileNameOut ) ;
if ( ext = = " ive " )
{
CompressTexturesVisitor ctv ;
root - > accept ( ctv ) ;
ctv . compress ( ) ;
}
else
{
std : : cout < < " Warning: compressing texture only supported when outputing to .ive " < < std : : endl ;
}
2004-07-22 19:59:58 +08:00
}
2003-05-21 20:15:45 +08:00
2003-04-16 20:46:06 +08:00
if ( osgDB : : writeNodeFile ( * root , fileNameOut ) )
{
osg : : notify ( osg : : NOTICE ) < < " Data written to ' " < < fileNameOut < < " '. " < < std : : endl ;
}
2003-02-21 22:05:39 +08:00
}
else
{
osg : : notify ( osg : : NOTICE ) < < " Error no data loaded. " < < std : : endl ;
return 1 ;
}
return 0 ;
}