diff --git a/Make/makedirdefs b/Make/makedirdefs index 8394b82f4..604d06713 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -13,6 +13,7 @@ SRC_DIRS = \ osgGA\ osgParticle\ osgGLUT\ + osgProducer\ osgText\ osgSim\ osgPlugins\ @@ -94,6 +95,7 @@ DEMOS_DIRS = \ osgoccluder\ osgparticle\ osgprerender\ + osgproducer\ osgshadowtexture\ osgreflect\ osgscribe\ diff --git a/VisualStudio/osg/osg.dsp b/VisualStudio/osg/osg.dsp index f0bec0c33..dd3ab527b 100755 --- a/VisualStudio/osg/osg.dsp +++ b/VisualStudio/osg/osg.dsp @@ -101,6 +101,14 @@ SOURCE=..\..\src\osg\AnimationPath.cpp # End Source File # Begin Source File +SOURCE=..\..\src\osg\ArgumentParser.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osg\ApplicationUsage.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\osg\Array.cpp # End Source File # Begin Source File @@ -457,6 +465,14 @@ SOURCE=..\..\Include\Osg\Array # End Source File # Begin Source File +SOURCE=..\..\Include\osg\ArgumentParser +# End Source File +# Begin Source File + +SOURCE=..\..\Include\osg\ApplicationUsage +# End Source File +# Begin Source File + SOURCE=..\..\Include\Osg\Billboard # End Source File # Begin Source File diff --git a/VisualStudio/osgText/osgText.dsp b/VisualStudio/osgText/osgText.dsp index 5b000b7f8..0443b5297 100644 --- a/VisualStudio/osgText/osgText.dsp +++ b/VisualStudio/osgText/osgText.dsp @@ -53,7 +53,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 freetype213.lib glu32.lib opengl32.lib /nologo /dll /pdb:none /machine:I386 /out:"../../bin/osgText.dll" /libpath:"../../lib" +# ADD LINK32 freetype.lib glu32.lib opengl32.lib /nologo /dll /pdb:none /machine:I386 /out:"../../bin/osgText.dll" /libpath:"../../lib" !ELSEIF "$(CFG)" == "Core osgText - Win32 Debug" @@ -79,7 +79,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 freetype213.lib glu32.lib opengl32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/osgTextd.dll" /pdbtype:sept /libpath:"../../lib" +# ADD LINK32 freetype.lib glu32.lib opengl32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/osgTextd.dll" /pdbtype:sept /libpath:"../../lib" # SUBTRACT LINK32 /pdb:none !ENDIF diff --git a/include/osg/ApplicationUsage b/include/osg/ApplicationUsage new file mode 100644 index 000000000..e42224c19 --- /dev/null +++ b/include/osg/ApplicationUsage @@ -0,0 +1,93 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSG_APPLICATIONUSAGE +#define OSG_APPLICATIONUSAGE 1 + +#include + +#include +#include +#include + +namespace osg { + +class SG_EXPORT ApplicationUsage +{ + public: + + static ApplicationUsage* instance(); + + ApplicationUsage() {} + + ApplicationUsage(const std::string& commandLineUsage); + + typedef std::map UsageMap; + + enum Type + { + COMMAND_LINE_OPTION, + ENVIRONMENTAL_VARIABLE, + KEYBOARD_MOUSE_BINDING + }; + + void addUsageExplanation(Type type,const std::string& option,const std::string& explanation); + + void setCommandLineUsage(const std::string& explanation) { _commandLineUsage=explanation; } + + const std::string& getCommandLineUsage() const { return _commandLineUsage; } + + + void addCommandLineOption(const std::string& option,const std::string& explanation); + + const UsageMap& getCommandLineOptions() const { return _commandLineOptions; } + + + void addEnvironmentalVariable(const std::string& option,const std::string& explanation); + + const UsageMap& getEnvironmentalVariables() const { return _environmentalVariables; } + + + void addKeyboardMouseBinding(const std::string& option,const std::string& explanation); + + const UsageMap& getKeyboardMouseBindings() const { return _keyboardMouse; } + + + void write(std::ostream& output,const UsageMap& um,unsigned int widthOfOutput=80); + + void write(std::ostream& output,unsigned int widthOfOutput=80); + + protected: + + + std::string _commandLineUsage; + UsageMap _commandLineOptions; + UsageMap _environmentalVariables; + UsageMap _keyboardMouse; + +}; + +class ApplicationUsageProxy +{ + public: + + /** register an explanation of commandline/evironmentalvaraible/keyboard mouse usage.*/ + ApplicationUsageProxy(ApplicationUsage::Type type,const std::string& option,const std::string& explanation) + { + ApplicationUsage::instance()->addUsageExplanation(type,option,explanation); + } +}; + +} + +#endif diff --git a/include/osg/ArgumentParser b/include/osg/ArgumentParser new file mode 100644 index 000000000..74c20bd08 --- /dev/null +++ b/include/osg/ArgumentParser @@ -0,0 +1,142 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSG_ARGUMENTPARSER +#define OSG_ARGUMENTPARSER 1 + +#include + +#include +#include + +namespace osg { + +class SG_EXPORT ArgumentParser +{ + public: + ArgumentParser(int* argc,char **argv): + _argc(argc), + _argv(argv) {} + + /** return the argument count.*/ + int& argc() { return *_argc; } + + /** return the argument array.*/ + char** argv() { return _argv; } + + /** return char* argument at specificed position.*/ + char* operator [] (int pos) { return _argv[pos]; } + + /** return const char* argument at specificed position.*/ + const char* operator [] (int pos) const { return _argv[pos]; } + + + + /** return the program name, as specified by argv[0] */ + std::string getProgramName() const; + + /** return the position of an occurance of a string in the argument list. + * return -1 when no string is found.*/ + int find(const std::string& str) const; + + /** return true if specified argument matches string.*/ + bool match(int pos, const std::string& str) const; + + /** return return true if specified parameter is an option in the form of -option or --option .*/ + bool isOption(int pos) const; + + /** return return true if specified parameter is an string, which can be any other string apart from an option.*/ + bool isString(int pos) const; + + /** return return true if specified parameter is an number.*/ + bool isNumber(int pos) const; + + bool containsOptions() const; + + /** remove one or more arguments from the argv argument list, and decrement the argc respectively.*/ + void remove(int pos,int num=1); + + /** search for an occurance of a string in the argument list, on sucess + * remove that occurance from the list and return true, otherwise return false.*/ + bool read(const std::string& str); + + /** search for an occurance of a string in the argument list followed by a string, + * on sucess set the value string with the second parameters and then + * remove the two entries from the list and return true, otherwise return false.*/ + bool read(const std::string& str,std::string& value1); + + /** search for an occurance of a string in the argument list followed by a two strings, + * on sucess set the value strings with the second & third parameters and then + * remove the three entries from the list and return true, otherwise return false.*/ + bool read(const std::string& str,std::string& value1,std::string& value2); + + /** search for an occurance of a string in the argument list followed by a three strings, + * on sucess set the value strings with the second & third & fourth parameters and then + * remove the four entries from the list and return true, otherwise return false.*/ + bool read(const std::string& str,std::string& value1,std::string& value2,std::string& value3); + + + /** search for an occurance of a string in the argument list followed by a numeric value, + * on sucess set the values with the second parameter and then + * remove the two entries from the list and return true, otherwise return false.*/ + bool read(const std::string& str,float& value); + + /** search for an occurance of a string in the argument list followed by two numeric values, + * on sucess set the values with the second & third parameters and then + * remove the three entries from the list and return true, otherwise return false.*/ + bool read(const std::string& str,float& value1,float& value2); + + /** search for an occurance of a string in the argument list followed by three numeric values, + * on sucess set the values with the second & third & fourth parameters and then + * remove the four entries from the list and return true, otherwise return false.*/ + bool read(const std::string& str,float& value1,float& value2,float& value3); + + + enum ErrorSeverity + { + BENIGN = 0, + CRITICAL = 1 + }; + + typedef std::map ErrorMessageMap; + + /** return the error flag, true if an error has occured when reading arguments.*/ + bool errors(ErrorSeverity severity=BENIGN) const; + + /** report an error message by adding to the ErrorMessageMap.*/ + void reportError(const std::string& message,ErrorSeverity severity=CRITICAL); + + /** for each remaining option report it as an unrecongnized.*/ + void reportRemainingOptionsAsUnrecognized(ErrorSeverity severity=BENIGN); + + /** return the error message, if any has occured.*/ + ErrorMessageMap& getErrorMessageMap() { return _errorMessageMap; } + + /** return the error message, if any has occured.*/ + const ErrorMessageMap& getErrorMessageMap() const { return _errorMessageMap; } + + /** write out error messages at an above specified .*/ + void writeErrorMessages(std::ostream& output,ErrorSeverity sevrity=BENIGN); + + + protected: + + int* _argc; + char** _argv; + ErrorMessageMap _errorMessageMap; + +}; + +} + +#endif diff --git a/include/osg/DisplaySettings b/include/osg/DisplaySettings index 99e07457f..713ebfd10 100644 --- a/include/osg/DisplaySettings +++ b/include/osg/DisplaySettings @@ -15,6 +15,7 @@ #define OSG_DisplaySettings 1 #include +#include #include #include @@ -59,6 +60,9 @@ class SG_EXPORT DisplaySettings : public osg::Referenced /** read the command line string list, removing any matched control sequences.*/ void readCommandLine(std::vector& commandLine); + + /** read the commandline arguments.*/ + void readCommandLine(ArgumentParser& parser); diff --git a/include/osgDB/ReadFile b/include/osgDB/ReadFile index 2fbe3f7ea..dece8399f 100644 --- a/include/osgDB/ReadFile +++ b/include/osgDB/ReadFile @@ -16,6 +16,7 @@ #include #include +#include #include @@ -51,6 +52,10 @@ extern OSGDB_EXPORT osg::Node* readNodeFile(const std::string& filename); * than one subgraph has been loaded.*/ extern OSGDB_EXPORT osg::Node* readNodeFiles(std::vector& commandLine); +/** Read an osg::Node subgraph from files, creating a osg::Group to contain the nodes if more + * than one subgraph has been loaded.*/ +extern OSGDB_EXPORT osg::Node* readNodeFiles(osg::ArgumentParser& parser); + } #endif diff --git a/include/osgDB/Registry b/include/osgDB/Registry index aa9de92ba..e9849c0ae 100644 --- a/include/osgDB/Registry +++ b/include/osgDB/Registry @@ -15,6 +15,7 @@ #define OSGDB_REGISTRY 1 #include +#include #include #include @@ -53,6 +54,9 @@ class OSGDB_EXPORT Registry : public osg::Referenced /** read the command line string list, removing any matched control sequences.*/ void readCommandLine(std::vector& commandLine); + /** read the command line arguments.*/ + void readCommandLine(osg::ArgumentParser& commandLine); + /** register an .fileextension alias to mapExt toExt, the later * should the the extension name of the readerwriter plugin library. * For example to map .tif files to the tiff loader, use @@ -203,6 +207,12 @@ inline void readCommandLine(std::vector& commandLine) Registry::instance()->readCommandLine(commandLine); } +/** read the command line arguments.*/ +inline void readCommandLine(osg::ArgumentParser& parser) +{ + Registry::instance()->readCommandLine(parser); +} + /** Proxy class for automatic registration of DotOsgWrappers with the Registry.*/ class RegisterDotOsgWrapperProxy { diff --git a/include/osgProducer/CameraGroup b/include/osgProducer/CameraGroup index 3afc789cf..2b515c80e 100644 --- a/include/osgProducer/CameraGroup +++ b/include/osgProducer/CameraGroup @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -38,6 +39,8 @@ class OSGPRODUCER_EXPORT CameraGroup : public Producer::CameraGroup CameraGroup(const std::string& configFile); + CameraGroup(osg::ArgumentParser& arguments); + virtual ~CameraGroup() {} diff --git a/include/osgProducer/FrameStatsHandler b/include/osgProducer/FrameStatsHandler index 50e8a76f2..cd8149423 100644 --- a/include/osgProducer/FrameStatsHandler +++ b/include/osgProducer/FrameStatsHandler @@ -1,10 +1,27 @@ -#ifndef FRAME_STATS_HANDLER +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGPRODUCER_FRAME_STATS_HANDLER +#define OSGPRODUCER_FRAME_STATS_HANDLER 1 + +#include + #include #include -namespace Producer { +namespace osgProducer { -class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callback +class FrameStatsHandler : public Producer::CameraGroup::StatsHandler, public Producer::Camera::Callback { public: FrameStatsHandler() @@ -14,15 +31,16 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb } void setArraySize(unsigned int size) { _fs.resize(size); } + unsigned int getArraySize() { return _fs.size(); } - void operator() (const CameraGroup &cg ) + void operator() (const Producer::CameraGroup &cg ) { _index = (_index + 1) % _fs.size(); _fs[_index] = cg.getFrameStats(); } - void operator() (const Camera &camera) + void operator() (const Producer::Camera &camera) { if (!camera.getInstrumentationMode()) return; @@ -43,10 +61,10 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb glLoadIdentity(); unsigned int lindex = (_index + 1) % _fs.size(); - Camera::TimeStamp zero = _fs[lindex]._startOfFrame; - int i; - double x1, x2, y1, y2; - for( int frame = 0; frame < _fs.size(); frame++ ) + Producer::Camera::TimeStamp zero = _fs[lindex]._startOfFrame; + unsigned int i; + double x1=0.0, x2=0.0, y1=0.0, y2=0.0; + for(unsigned int frame = 0; frame < _fs.size(); frame++ ) { CameraGroup::FrameStats fs = _fs[(lindex + frame) % _fs.size()]; y1 = 0.0; @@ -65,11 +83,11 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb for( i = 0; i < fs.getNumFrameTimeStampSets(); i++ ) { - Camera::FrameTimeStampSet fts = fs.getFrameTimeStampSet(i); + Producer::Camera::FrameTimeStampSet fts = fs.getFrameTimeStampSet(i); y1 += 13.0; y2 = y1 + 10.0; - x1 = fts[Camera::BeginCull] - zero; - x2 = fts[Camera::EndCull] - zero; + x1 = fts[Producer::Camera::BeginCull] - zero; + x2 = fts[Producer::Camera::EndCull] - zero; glColor4f( 0.0, 0.0, 1.0, 0.5 ); glVertex2d( x1, y1); @@ -77,8 +95,8 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb glVertex2d( x2, y2); glVertex2d( x1, y2); - x1 = fts[Camera::BeginDraw] - zero; - x2 = fts[Camera::EndDraw] - zero; + x1 = fts[Producer::Camera::BeginDraw] - zero; + x2 = fts[Producer::Camera::EndDraw] - zero; glColor4f( 1.0, 0.0, 0.0, 0.5 ); glVertex2d( x1, y1); @@ -99,8 +117,8 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb for( i = 0; i < fs.getNumFrameTimeStampSets(); i++ ) { y2 = y1 + 11; - Camera::FrameTimeStampSet fts = fs.getFrameTimeStampSet(i); - Camera::TimeStamp vsync = fts[Camera::Vsync]; + Producer::Camera::FrameTimeStampSet fts = fs.getFrameTimeStampSet(i); + Producer::Camera::TimeStamp vsync = fts[Producer::Camera::Vsync]; double x1 = vsync - zero; glColor4f( 1.0, 1.0, 0.0, 0.5 ); glVertex2d( x1, y1 ); @@ -136,8 +154,10 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb } private: - std::vector _fs; + std::vector _fs; unsigned int _index; }; + } + #endif diff --git a/include/osgProducer/StatsEventHandler b/include/osgProducer/StatsEventHandler index fd2ca6c1f..c79fb9ace 100644 --- a/include/osgProducer/StatsEventHandler +++ b/include/osgProducer/StatsEventHandler @@ -8,7 +8,7 @@ class StatsEventHandler : public osgGA::GUIEventHandler StatsEventHandler(osgProducer::Viewer* cg):_cg(cg) {} - virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa) + virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&) { if(!_cg) return false; diff --git a/include/osgProducer/Viewer b/include/osgProducer/Viewer index bb120ffa1..4ebc6a02e 100644 --- a/include/osgProducer/Viewer +++ b/include/osgProducer/Viewer @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -38,6 +39,8 @@ class OSGPRODUCER_EXPORT Viewer : public CameraGroup, public osgGA::GUIActionAda Viewer(const std::string& configFile); + Viewer(osg::ArgumentParser& arguments); + virtual ~Viewer() {} diff --git a/src/Demos/osgproducer/Makefile b/src/Demos/osgproducer/Makefile index 98ba7f9c9..735544dbc 100644 --- a/src/Demos/osgproducer/Makefile +++ b/src/Demos/osgproducer/Makefile @@ -1,4 +1,4 @@ -TOPDIR = ../../.. +TOPDIR = ../../../ include $(TOPDIR)/Make/makedefs CXXFILES =\ diff --git a/src/Demos/osgproducer/osgproducer_viewer.cpp b/src/Demos/osgproducer/osgproducer_viewer.cpp index 03ad4abf1..c0bb8b38f 100644 --- a/src/Demos/osgproducer/osgproducer_viewer.cpp +++ b/src/Demos/osgproducer/osgproducer_viewer.cpp @@ -2,6 +2,10 @@ //Distributed under the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE (LGPL) //as published by the Free Software Foundation. +#include +#include + + #include #include @@ -15,83 +19,85 @@ int main( int argc, char **argv ) { - // create the commandline args. + // 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. + osg::ApplicationUsage::instance()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ..."); + osg::ApplicationUsage::instance()->addCommandLineOption("-h or --help","Display this information"); + osg::ApplicationUsage::instance()->addCommandLineOption("-p ","Specify camera path file to animate the camera through the loaded scene"); + + + // construct the viewer. + osgProducer::Viewer viewer(arguments); + + // set up the value with sensible default event handlers. + viewer.setUpViewer(); + + // if a pathfile has been specified on command line use it to animate the camera via an AnimationPathManipulator. std::string pathfile; - std::string configfile; - std::vector commandLine; - for(int i=1;i= argc ) { - std::cout << "path argument required for -p option."<= argc ) { - std::cout << "path argument required for -c option."<readCommandLine(commandLine); - osgDB::readCommandLine(commandLine); - - osgProducer::Viewer* viewer = 0; - if (!configfile.empty()) viewer = new osgProducer::Viewer(configfile); - else viewer = new osgProducer::Viewer; - - - // configure the plugin registry from the commandline arguments, and - // eat any parameters that have been matched. - osgDB::readCommandLine(commandLine); - - - // read the scene. - osg::ref_ptr loadedModel = osgDB::readNodeFiles(commandLine); - if (!loadedModel) return 1; - - // optimize it, remove rendundent nodes and state etc. - osgUtil::Optimizer optimizer; - optimizer.optimize(loadedModel.get()); - - - // set up the value with sensible defaults. - viewer->setUpViewer(); - - if( !pathfile.empty() ) { + while (arguments.read("-p",pathfile)) + { osg::ref_ptr apm = new osgGA::AnimationPathManipulator(pathfile); if( apm.valid() && apm->valid() ) { - unsigned int num = viewer->addCameraManipulator(apm.get()); - viewer->selectCameraManipulator(num); + unsigned int num = viewer.addCameraManipulator(apm.get()); + viewer.selectCameraManipulator(num); } } + + // if user request help pritn it out to cout. + if (arguments.read("-h") || arguments.read("--help")) + { + osg::ApplicationUsage::instance()->write(cout); + return 1; + } + + + // read the scene from the list of file specified commandline args. + osg::ref_ptr loadedModel = osgDB::readNodeFiles(arguments); + + // any option left unread a converted into errors to write out later. + arguments.reportRemainingOptionsAsUnrecognized(); + + // report any errors if they have occured when parsing the program aguments. + if (arguments.errors()) + { + arguments.writeErrorMessages(cout); + return 1; + } + + + // if no model has been successfully loaded report failure. + if (!loadedModel) + { + std::cout << arguments.getProgramName() <<": No input files" << std::endl; + return 1; + } + + + // optimize the scene graph, remove rendundent nodes and state etc. + osgUtil::Optimizer optimizer; + optimizer.optimize(loadedModel.get()); + // set the scene to render - viewer->setSceneData(loadedModel.get()); + viewer.setSceneData(loadedModel.get()); // create the windows and run the threads. - viewer->realize(Producer::CameraGroup::ThreadPerCamera); + viewer.realize(Producer::CameraGroup::ThreadPerCamera); - while( !viewer->done() ) + while( !viewer.done() ) { // wait for all cull and draw threads to complete. - viewer->sync(); + viewer.sync(); // update the scene by traversing it with the the update visitor which will // call all node update callbacks and animations. - viewer->update(); + viewer.update(); // fire off the cull and draw traversals of the scene. - viewer->frame(); + viewer.frame(); } return 0; diff --git a/src/osg/ApplicationUsage.cpp b/src/osg/ApplicationUsage.cpp new file mode 100644 index 000000000..0bfdc3f38 --- /dev/null +++ b/src/osg/ApplicationUsage.cpp @@ -0,0 +1,171 @@ +#include + +using namespace osg; + +ApplicationUsage::ApplicationUsage(const std::string& commandLineUsage): + _commandLineUsage(commandLineUsage) +{ +} + +ApplicationUsage* ApplicationUsage::instance() +{ + static ApplicationUsage s_applicationUsage; + return &s_applicationUsage; +} + +void ApplicationUsage::addUsageExplanation(Type type,const std::string& option,const std::string& explanation) +{ + switch(type) + { + case(COMMAND_LINE_OPTION): + addCommandLineOption(option,explanation); + break; + case(ENVIRONMENTAL_VARIABLE): + addEnvironmentalVariable(option,explanation); + break; + case(KEYBOARD_MOUSE_BINDING): + addKeyboardMouseBinding(option,explanation); + break; + } +} + +void ApplicationUsage::addCommandLineOption(const std::string& option,const std::string& explanation) +{ + _commandLineOptions[option]=explanation; +} + +void ApplicationUsage::addEnvironmentalVariable(const std::string& option,const std::string& explanation) +{ + _environmentalVariables[option]=explanation; +} + +void ApplicationUsage::addKeyboardMouseBinding(const std::string& option,const std::string& explanation) +{ + _keyboardMouse[option]=explanation; +} + +void ApplicationUsage::write(std::ostream& output, const ApplicationUsage::UsageMap& um,unsigned int widthOfOutput) +{ + unsigned int maxNumCharsInOptions = 0; + ApplicationUsage::UsageMap::const_iterator citr; + for(citr=um.begin(); + citr!=um.end(); + ++citr) + { + maxNumCharsInOptions = std::max(maxNumCharsInOptions,citr->first.length()); + } + + unsigned int fullWidth = widthOfOutput; + unsigned int optionPos = 2; + unsigned int optionWidth = maxNumCharsInOptions; + unsigned int explanationPos = 2+maxNumCharsInOptions+2; + unsigned int explanationWidth = fullWidth-explanationPos; + + std::string line; + + for(citr=um.begin(); + citr!=um.end(); + ++citr) + { + line.assign(fullWidth,' '); + line.replace(optionPos,optionWidth,citr->first); + + const std::string& explanation = citr->second; + unsigned int pos = 0; + unsigned int offset = 0; + bool firstInLine = true; + while (pos0 && + explanation[pos+width]!=' ' && + explanation[pos+width]!='\n') --width; + + if (width==0) + { + // word must be longer than a whole line so will need + // to concatinate it. + width = explanationWidth-1; + concatinated = true; + } + } + + line.replace(explanationPos+offset,explanationWidth, explanation, pos, width); + if (concatinated) output << line << '-' << std::endl; + else output << line << std::endl; + + + // move to the next line of output. + line.assign(fullWidth,' '); + pos += width+extraSkip; + + + } + + } +} + +void ApplicationUsage::write(std::ostream& output,unsigned int widthOfOutput) +{ + + output << "Usage: "< + +using namespace osg; + +std::string ArgumentParser::getProgramName() const +{ + if (_argc>0) return std::string(_argv[0]); + return ""; +} + +int ArgumentParser::find(const std::string& str) const +{ + for(int pos=1;pos<*_argc;++pos) + { + if (str==_argv[pos]) return pos; + } + return 0; +} + +bool ArgumentParser::match(int pos, const std::string& str) const +{ + return pos<*_argc && str==_argv[pos]; +} + +bool ArgumentParser::isOption(int pos) const +{ + return (pos<*_argc && _argv[pos][0]=='-'); +} + +bool ArgumentParser::isString(int pos) const +{ + return pos<*_argc && !isOption(pos); +} + +bool ArgumentParser::isNumber(int pos) const +{ + if (pos>=*_argc) return false; + + bool hadPlusMinus = false; + bool hadDecimalPlace = false; + bool hadExponent = false; + bool couldBeInt = true; + bool couldBeFloat = true; + int noZeroToNine = 0; + + const char* ptr = _argv[pos]; + + // check if could be a hex number. + if (strncmp(ptr,"0x",2)==0) + { + // skip over leading 0x, and then go through rest of string + // checking to make sure all values are 0...9 or a..f. + ptr+=2; + while ( + *ptr!=0 && + ((*ptr>='0' && *ptr<='9') || + (*ptr>='a' && *ptr<='f') || + (*ptr>='A' && *ptr<='F')) + ) + { + ++ptr; + } + + // got to end of string without failure, therefore must be a hex integer. + if (*ptr==0) return true; + } + + ptr = _argv[pos]; + // check if a float or an int. + while (*ptr!=0 && couldBeFloat) + { + if (*ptr=='+' || *ptr=='-') + { + if (hadPlusMinus) + { + couldBeInt = false; + couldBeFloat = false; + } else hadPlusMinus = true; + } + else if (*ptr>='0' && *ptr<='9') + { + noZeroToNine++; + } + else if (*ptr=='.') + { + if (hadDecimalPlace) + { + couldBeInt = false; + couldBeFloat = false; + } + else + { + hadDecimalPlace = true; + couldBeInt = false; + } + } + else if (*ptr=='e' || *ptr=='E') + { + if (hadExponent || noZeroToNine==0) + { + couldBeInt = false; + couldBeFloat = false; + } + else + { + hadExponent = true; + couldBeInt = false; + hadDecimalPlace = false; + hadPlusMinus = false; + noZeroToNine=0; + } + } + else + { + couldBeInt = false; + couldBeFloat = false; + } + ++ptr; + } + + if (couldBeInt && noZeroToNine>0) return true; + if (couldBeFloat && noZeroToNine>0) return true; + + return false; + +} + +bool ArgumentParser::containsOptions() const +{ + for(int pos=1;pos<*_argc;++pos) + { + if (isOption(pos)) return true; + } + return false; +} + + +void ArgumentParser::remove(int pos,int num) +{ + if (num==0) return; + + for(;pos+num<*_argc;++pos) + { + _argv[pos]=_argv[pos+num]; + } + for(;pos<*_argc;++pos) + { + _argv[pos]=0; + } + *_argc-=num; +} + +bool ArgumentParser::read(const std::string& str) +{ + int pos=find(str); + if (pos<=0) return false; + remove(pos); + return true; +} + +bool ArgumentParser::read(const std::string& str,std::string& value1) +{ + int pos=find(str); + if (pos<=0) return false; + if (!isString(pos+1)) + { + reportError("argument to `"+str+"` is missing"); + return false; + } + value1 = _argv[pos+1]; + remove(pos,2); + return true; +} + +bool ArgumentParser::read(const std::string& str,std::string& value1,std::string& value2) +{ + int pos=find(str); + if (pos<=0) return false; + if (!isString(pos+1) || !isString(pos+2) ) + { + reportError("argument to `"+str+"` is missing"); + return false; + } + value1 = _argv[pos+1]; + value2 = _argv[pos+2]; + remove(pos,3); + return true; +} + +bool ArgumentParser::read(const std::string& str,std::string& value1,std::string& value2,std::string& value3) +{ + int pos=find(str); + if (pos<=0) return false; + if (!isString(pos+1) || !isString(pos+2) || !isString(pos+3)) + { + reportError("argument to `"+str+"` is missing"); + return false; + } + value1 = _argv[pos+1]; + value2 = _argv[pos+2]; + value3 = _argv[pos+3]; + remove(pos,4); + return true; +} + + +bool ArgumentParser::read(const std::string& str,float& value1) +{ + int pos=find(str); + if (pos<=0) return false; + if (!isNumber(pos+1)) + { + reportError("argument to `"+str+"` is missing"); + return false; + } + value1 = atof(_argv[pos+1]); + remove(pos,2); + return true; +} + +bool ArgumentParser::read(const std::string& str,float& value1,float& value2) +{ + int pos=find(str); + if (pos<=0) return false; + if (!isNumber(pos+1) || !isNumber(pos+2) ) + { + reportError("argument to `"+str+"` is missing"); + return false; + } + value1 = atof(_argv[pos+1]); + value2 = atof(_argv[pos+2]); + remove(pos,3); + return true; +} + +bool ArgumentParser::read(const std::string& str,float& value1,float& value2,float& value3) +{ + int pos=find(str); + if (pos<=0) return false; + if (!isNumber(pos+1) || !isNumber(pos+2) || !isNumber(pos+3)) + { + reportError("argument to `"+str+"` is missing"); + return false; + } + value1 = atof(_argv[pos+1]); + value2 = atof(_argv[pos+2]); + value3 = atof(_argv[pos+3]); + remove(pos,4); + return true; +} + +bool ArgumentParser::errors(ErrorSeverity severity) const +{ + for(ErrorMessageMap::const_iterator itr=_errorMessageMap.begin(); + itr!=_errorMessageMap.end(); + ++itr) + { + if (itr->second>=severity) return true; + } + return false; +} + +void ArgumentParser::reportError(const std::string& message,ErrorSeverity severity) +{ + _errorMessageMap[message]=severity; +} + +void ArgumentParser::reportRemainingOptionsAsUnrecognized(ErrorSeverity severity) +{ + for(int pos=1;possecond>=severity) + { + output<first< +#include #include #include @@ -104,6 +105,17 @@ void DisplaySettings::setDefaults() #endif } +ApplicationUsageProxy e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO_MODE ","QUAD_BUFFER | ANAGLYPHIC | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE"); +ApplicationUsageProxy e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO ","OFF | ON"); +ApplicationUsageProxy e2(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EYE_SEPARATION ","physical distance between eyes"); +ApplicationUsageProxy e3(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_DISTANCE ","physical distance between eyes and screen"); +ApplicationUsageProxy e4(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_HEIGHT ","physical screen height"); +ApplicationUsageProxy e5(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING ","LEFT_EYE_LEFT_VIEWPORT | LEFT_EYE_RIGHT_VIEWPORT"); +ApplicationUsageProxy e8(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION ","number of pixels between viewports"); +ApplicationUsageProxy e9(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING ","LEFT_EYE_TOP_VIEWPORT | LEFT_EYE_BOTTOM_VIEWPORT"); +ApplicationUsageProxy e11(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_SEPARATION ","number of pixels between viewports"); +ApplicationUsageProxy e12(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS ","maximum number of graphics contexts to be used with applications."); + void DisplaySettings::readEnvironmentalVariables() { char *ptr; @@ -281,3 +293,31 @@ void DisplaySettings::readCommandLine(std::vector& commandLine) } } + +void DisplaySettings::readCommandLine(ArgumentParser& parser) +{ + int pos; + while ((pos=parser.find("-stereo"))!=0) + { + if (parser.match(pos+1,"ANAGLYPHIC")) { parser.remove(pos,2); _stereo = true;_stereoMode = ANAGLYPHIC; } + else if (parser.match(pos+1,"QUAD_BUFFER")) { parser.remove(pos,2); _stereo = true;_stereoMode = QUAD_BUFFER; } + else if (parser.match(pos+1,"HORIZONTAL_SPLIT")) { parser.remove(pos,2); _stereo = true;_stereoMode = HORIZONTAL_SPLIT; } + else if (parser.match(pos+1,"VERTICAL_SPLIT")) { parser.remove(pos,2); _stereo = true;_stereoMode = VERTICAL_SPLIT; } + else if (parser.match(pos+1,"LEFT_EYE")) { parser.remove(pos,2); _stereo = true;_stereoMode = LEFT_EYE; } + else if (parser.match(pos+1,"RIGHT_EYE")) { parser.remove(pos,2); _stereo = true;_stereoMode = RIGHT_EYE; } + else if (parser.match(pos+1,"ON")) { parser.remove(pos,2); _stereo = true; } + else if (parser.match(pos+1,"OFF")) { parser.remove(pos,2); _stereo = false; } + else { parser.remove(pos); _stereo = true; } + } + + while (parser.read("-rgba")) + { + _RGB = true; + _minimumNumberAlphaBits = 1; + } + + while (parser.read("-stencil")) + { + _minimumNumberStencilBits = 1; + } +} diff --git a/src/osg/Makefile b/src/osg/Makefile index 7a26dc72d..dc2567654 100644 --- a/src/osg/Makefile +++ b/src/osg/Makefile @@ -4,6 +4,8 @@ include $(TOPDIR)/Make/makedefs CXXFILES =\ AlphaFunc.cpp\ AnimationPath.cpp\ + ApplicationUsage.cpp\ + ArgumentParser.cpp\ Array.cpp\ Billboard.cpp\ BoundingBox.cpp\ diff --git a/src/osgDB/ReadFile.cpp b/src/osgDB/ReadFile.cpp index 79aca2392..ec239fc04 100644 --- a/src/osgDB/ReadFile.cpp +++ b/src/osgDB/ReadFile.cpp @@ -96,3 +96,52 @@ Node* osgDB::readNodeFiles(std::vector& commandLine) } } + +Node* osgDB::readNodeFiles(osg::ArgumentParser& arguments) +{ + osgDB::readCommandLine(arguments); + + typedef std::vector NodeList; + NodeList nodeList; + + // note currently doesn't delete the loaded file entries from the command line yet... + + for(int pos=1;posgetName().empty()) node->setName( arguments[pos] ); + nodeList.push_back(node); + } + + } + } + + if (nodeList.empty()) + { + return NULL; + } + + if (nodeList.size()==1) + { + return nodeList.front(); + } + else // size >1 + { + osg::Group* group = new osg::Group; + for(NodeList::iterator itr=nodeList.begin(); + itr!=nodeList.end(); + ++itr) + { + group->addChild(*itr); + } + + return group; + } + +} diff --git a/src/osgDB/Registry.cpp b/src/osgDB/Registry.cpp index 66a355c54..aafc009ce 100644 --- a/src/osgDB/Registry.cpp +++ b/src/osgDB/Registry.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -83,7 +84,11 @@ Registry::~Registry() { } - +#ifndef WIN32 +osg::ApplicationUsageProxy e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH [:path]..","Paths for locating datafiles"); +#else +osg::ApplicationUsageProxy e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH [;path]..","Paths for locating datafiles"); +#endif void Registry::initDataFilePathList() { @@ -106,6 +111,12 @@ void Registry::initDataFilePathList() PrintFilePathList(osg::notify(INFO),getDataFilePathList()); } +#ifndef WIN32 +osg::ApplicationUsageProxy e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH [:path]..","Paths for locating libraries/ plugins"); +#else +osg::ApplicationUsageProxy e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH [;path]..","Paths for locating libraries/ plugins"); +#endif + void Registry::initLibraryFilePathList() { // @@ -266,6 +277,27 @@ void Registry::readCommandLine(std::vector& commandLine) } } +void Registry::readCommandLine(osg::ArgumentParser& parser) +{ + + std::string value; + while(parser.read("-l",value)) + { + loadLibrary(value); + } + + while(parser.read("-e",value)) + { + std::string libName = createLibraryNameForExt(value); + loadLibrary(libName); + } + + while(parser.read("-O",value)) + { + setOptions(new osgDB::ReaderWriter::Options(value)); + } +} + void Registry::addDotOsgWrapper(DotOsgWrapper* wrapper) { if (wrapper==0L) return; diff --git a/src/osgProducer/CameraGroup.cpp b/src/osgProducer/CameraGroup.cpp index e1ef9715e..ba19d0ba3 100644 --- a/src/osgProducer/CameraGroup.cpp +++ b/src/osgProducer/CameraGroup.cpp @@ -14,18 +14,33 @@ std::string findCameraConfigFile(const std::string& configFile) else return foundFile; } +std::string extractCameraConfigFile(osg::ArgumentParser& arguments) +{ + std::string filename; + if (arguments.read("-c",filename)) return filename; + return ""; +} + CameraGroup::CameraGroup() : Producer::CameraGroup() { _init(); } -CameraGroup::CameraGroup(Producer::CameraConfig *cfg): Producer::CameraGroup(cfg) +CameraGroup::CameraGroup(Producer::CameraConfig *cfg): + Producer::CameraGroup(cfg) { _init(); } -CameraGroup::CameraGroup(const std::string& configFile) : Producer::CameraGroup(findCameraConfigFile(configFile)) +CameraGroup::CameraGroup(const std::string& configFile): + Producer::CameraGroup(findCameraConfigFile(configFile)) +{ + _init(); +} + +CameraGroup::CameraGroup(osg::ArgumentParser& arguments): + Producer::CameraGroup(extractCameraConfigFile(arguments)) { _init(); } diff --git a/src/osgProducer/Viewer.cpp b/src/osgProducer/Viewer.cpp index 604f4dc02..0d7714b3b 100644 --- a/src/osgProducer/Viewer.cpp +++ b/src/osgProducer/Viewer.cpp @@ -6,6 +6,9 @@ #include +#include + +#include #include #include #include @@ -13,6 +16,7 @@ using namespace osgProducer; + Viewer::Viewer(): _done(0), _frameNumber(0), @@ -36,6 +40,27 @@ Viewer::Viewer(const std::string& configFile): { } +Viewer::Viewer(osg::ArgumentParser& arguments): + CameraGroup(arguments), + _done(false), + _frameNumber(0), + _kbmcb(0) +{ + osg::DisplaySettings::instance()->readCommandLine(arguments); + + std::string pathfile; + while (arguments.read("-p",pathfile)) + { + osg::ref_ptr apm = new osgGA::AnimationPathManipulator(pathfile); + if( apm.valid() && apm->valid() ) + { + unsigned int num = addCameraManipulator(apm.get()); + selectCameraManipulator(num); + } + } +} + + void Viewer::setUpViewer(unsigned int options) { @@ -108,7 +133,7 @@ void Viewer::setUpViewer(unsigned int options) if (options&STATS_MANIPULATOR) { // register the drawing of stats to pipe 0. - Producer::FrameStatsHandler* fsh = new Producer::FrameStatsHandler; + FrameStatsHandler* fsh = new FrameStatsHandler; setStatsHandler(fsh); getCamera(0)->addPostDrawCallback(fsh);