diff --git a/VisualStudio/osgPlugins/flt/flt.dsp b/VisualStudio/osgPlugins/flt/flt.dsp index db1c7ce8a..f3b6f1642 100644 --- a/VisualStudio/osgPlugins/flt/flt.dsp +++ b/VisualStudio/osgPlugins/flt/flt.dsp @@ -131,6 +131,10 @@ SOURCE=..\..\..\src\osgPlugins\flt\FaceRecord.cpp # End Source File # Begin Source File +SOURCE=..\..\..\src\osgPlugins\flt\FindExternalModelVisitor.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\src\osgPlugins\flt\flt.cpp # End Source File # Begin Source File @@ -323,6 +327,10 @@ SOURCE=..\..\..\src\osgPlugins\flt\FaceRecord.h # End Source File # Begin Source File +SOURCE=..\..\..\src\osgPlugins\flt\FindExternalModelVisitor.h +# End Source File +# Begin Source File + SOURCE=..\..\..\src\osgPlugins\flt\flt.h # End Source File # Begin Source File diff --git a/src/osgPlugins/flt/ExternalRecord.cpp b/src/osgPlugins/flt/ExternalRecord.cpp index f05a663a1..bfae28a9a 100644 --- a/src/osgPlugins/flt/ExternalRecord.cpp +++ b/src/osgPlugins/flt/ExternalRecord.cpp @@ -25,6 +25,65 @@ ExternalRecord::~ExternalRecord() { } +/** + * Return the filename of the external record. External references are + * specified as either: + * filename - include the entire file + * filename - include only the specified model from the file + * + * Therefore, the filename is either the entire string or the portion of the + * string prior to the first '<' character. + **/ +const std::string ExternalRecord::getFilename( void ) +{ + std::string wholeFilename(getData()->szPath); + std::string filename; + + size_t pos = wholeFilename.find_first_of( "<" ); + + if (pos != std::string::npos) + { + filename = wholeFilename.substr( 0, pos ); + } + else + { + filename = wholeFilename; + } + + return filename; +} + + + +/** + * Return the modelname of the external record. External references are + * specified as either: + * filename - include the entire file + * filename - include only the specified model from the file + * + * Therefore, the modelname is the portion of the string between '<' and '>' + * characters when those characters are present. Otherwise there is no + * modelname. + **/ +std::string ExternalRecord::getModelName( void ) +{ + std::string wholeFilename(getData()->szPath); + std::string modelName; + + size_t pos = wholeFilename.find_first_of( "<" ); + + if (pos != std::string::npos) + { + size_t pos2 = wholeFilename.find_first_of( ">" ); + + // Starting after the first '<', return the characters prior to the + // first '>'. + modelName = wholeFilename.substr( pos+1, pos2-pos-1 ); + } + + return modelName; +} + void ExternalRecord::setExternal(FltFile* pExternal) { diff --git a/src/osgPlugins/flt/ExternalRecord.h b/src/osgPlugins/flt/ExternalRecord.h index 65e5eaf31..6ef0379d2 100644 --- a/src/osgPlugins/flt/ExternalRecord.h +++ b/src/osgPlugins/flt/ExternalRecord.h @@ -45,8 +45,11 @@ class ExternalRecord : public PrimNodeRecord SExternalReference* getData() const { return (SExternalReference*)_pData; } void setExternal(FltFile* pExternal); + FltFile* getExternal() { return _fltfile.get(); } - const std::string getFilename( void ) const { return std::string(getData()->szPath); } + + const std::string getFilename( void ); + std::string getModelName() ; enum Flag { diff --git a/src/osgPlugins/flt/FindExternalModelVisitor.cpp b/src/osgPlugins/flt/FindExternalModelVisitor.cpp new file mode 100644 index 000000000..7d41888e9 --- /dev/null +++ b/src/osgPlugins/flt/FindExternalModelVisitor.cpp @@ -0,0 +1,18 @@ +// FindExternalModelVisitor.cpp + +#include "FindExternalModelVisitor.h" + +using namespace flt; + + +/** + * + */ +void FindExternalModelVisitor::apply( osg::Node &node ) +{ + if ( node.getName() == _modelName ) + _model = &node; // Store the node. No need to process children. + else + traverse( node ); +} + diff --git a/src/osgPlugins/flt/FindExternalModelVisitor.h b/src/osgPlugins/flt/FindExternalModelVisitor.h new file mode 100644 index 000000000..35b78bc30 --- /dev/null +++ b/src/osgPlugins/flt/FindExternalModelVisitor.h @@ -0,0 +1,36 @@ +// FindExternalModelVisitor.h + +#ifndef __FIND_EXTERNAL_MODEL_VISITOR_H_ +#define __FIND_EXTERNAL_MODEL_VISITOR_H_ + +#include +#include +#include + +namespace flt { + +/** + * A visitor to find a named node. + */ +class FindExternalModelVisitor : public osg::NodeVisitor +{ +public: + FindExternalModelVisitor( ) : osg::NodeVisitor( TRAVERSE_ALL_CHILDREN ) {} + + virtual void apply( osg::Node &node ); + + void setModelName( std::string modelName ) { _modelName = modelName; } + + osg::Node *getModel() { return _model.get(); } + +private: + + std::string _modelName; + osg::ref_ptr _model; + +}; + +}; // end namespace flt + +#endif // __FIND_EXTERNAL_MODEL_VISITOR_H_ + diff --git a/src/osgPlugins/flt/FltFile.cpp b/src/osgPlugins/flt/FltFile.cpp index 4e5b04f86..8125c5b98 100644 --- a/src/osgPlugins/flt/FltFile.cpp +++ b/src/osgPlugins/flt/FltFile.cpp @@ -209,7 +209,7 @@ bool FltFile::readFile(const std::string& fileName) MaterialPool* pMaterialPool = NULL; LtPtAppearancePool* pLtPtAppearancePool = NULL; LtPtAnimationPool* pLtPtAnimationPool = NULL; - std::string filename(pSExternal->szPath); + std::string filename( rec.getFilename() ); osg::notify(osg::INFO) << "External=" << filename << std::endl; diff --git a/src/osgPlugins/flt/GNUmakefile b/src/osgPlugins/flt/GNUmakefile index 3a9424cd5..461eb3e26 100644 --- a/src/osgPlugins/flt/GNUmakefile +++ b/src/osgPlugins/flt/GNUmakefile @@ -48,6 +48,7 @@ CXXFILES =\ MultiTextureRecord.cpp\ UVListRecord.cpp\ BSPRecord.cpp\ + FindExternalModelVisitor.cpp\ # PointLight.cpp\ diff --git a/src/osgPlugins/flt/flt2osg.cpp b/src/osgPlugins/flt/flt2osg.cpp index 9b4e7189b..8df34e9f0 100644 --- a/src/osgPlugins/flt/flt2osg.cpp +++ b/src/osgPlugins/flt/flt2osg.cpp @@ -84,6 +84,7 @@ #include "LightSourcePaletteRecord.h" #include "AttrData.h" #include "BSPRecord.h" +#include "FindExternalModelVisitor.h" static int dprint = 0 ; #define DPRINT if(dprint)fprintf @@ -2448,7 +2449,47 @@ osg::Group* ConvertFromFLT::visitExternal(osg::Group& osgParent, ExternalRecord* pFile->setDesiredUnits( rec->getFltFile()->getDesiredUnits() ); external = pFile->convert(); if (external) - visitAncillary(osgParent, *external, rec)->addChild(external); + { + osg::Group *tempParent = visitAncillary(osgParent, *external, rec); + + // In the situation in which only one model is required from an + // externally referenced file, it would be more efficient to only + // convert that one model from the FltFile records. (This would be + // the preferred method if this loader is rewritten.) However, + // since this situation is fairly rare and it is currently much + // more straight forward to work with the OSG structure, we will + // just pull out the part of the OSG tree that is needed at this + // point. + + // If a model name was specified, find and add the node with + // that name. Otherwise, add the entire tree. + + std::string modelName = rec->getModelName(); + if ( modelName.empty() ) + { + // Add the entire externally referenced file + tempParent->addChild(external); + } + else + { + // Find the specified model + FindExternalModelVisitor findExternalModelVisitor; + findExternalModelVisitor.setModelName( modelName ); + external->accept( findExternalModelVisitor ); + osg::Node *model = findExternalModelVisitor.getModel(); + if (model) + { + tempParent->addChild(model); + } + else + { + osg::notify(osg::WARN) << "In ConvertFromFLT::visitExternal," + << " the requested model " << modelName + << " was not found in external file " + << rec->getFilename() << std::endl; + } + } + } } return external;