From Sondra Iversion "Loading a single model from an externally

referenced file is a standard option for OpenFlight and is specified by
including the modelname in angle brackets, such as:  filename<modelname>.

The attached code identifies and handles this case."
This commit is contained in:
Robert Osfield
2004-10-07 10:03:27 +00:00
parent d77e6a0829
commit 0fcc08d867
8 changed files with 169 additions and 3 deletions

View File

@@ -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

View File

@@ -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<modelname> - 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<modelname> - 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)
{

View File

@@ -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
{

View File

@@ -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 );
}

View File

@@ -0,0 +1,36 @@
// FindExternalModelVisitor.h
#ifndef __FIND_EXTERNAL_MODEL_VISITOR_H_
#define __FIND_EXTERNAL_MODEL_VISITOR_H_
#include <iostream>
#include <osg/Node>
#include <osg/NodeVisitor>
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<osg::Node> _model;
};
}; // end namespace flt
#endif // __FIND_EXTERNAL_MODEL_VISITOR_H_

View File

@@ -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;

View File

@@ -48,6 +48,7 @@ CXXFILES =\
MultiTextureRecord.cpp\
UVListRecord.cpp\
BSPRecord.cpp\
FindExternalModelVisitor.cpp\
# PointLight.cpp\

View File

@@ -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;