Files
OpenSceneGraph/src/osgPlugins/flt/FltFile.cpp
Robert Osfield cfe376b644 From Paul Martz, with a couple of mods by Robert Osfield:
"Changes to return the lat/long origin of an
OpenFlight model as userData of the root node object."
2004-03-02 16:12:11 +00:00

312 lines
8.5 KiB
C++

#include "FltFile.h"
#include "Registry.h"
#include "Record.h"
#include "RecordVisitor.h"
#include "ExternalRecord.h"
#include "flt2osg.h" // ConvertFromFLT
#include "Input.h"
#include <osg/Node>
#include <osg/NodeVisitor>
#include <osg/Notify>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgSim/GeographicLocation>
#include <string>
using namespace flt;
FltFile::FltFile(
ColorPool* pColorPool,
TexturePool* pTexturePool,
MaterialPool* pMaterialPool)
{
_useTextureAlphaForTransparancyBinning = true;
_doUnitsConversion = true;
_desiredUnits = ConvertToMeters;
if (pColorPool)
{
// use external color palette, ignore internal
_useInternalColorPalette = false;
setColorPool( pColorPool );
}
else
{
// use internal color palette
_useInternalColorPalette = true;
setColorPool( new ColorPool );
}
if (pTexturePool)
{
// use external texture palette, ignore internal
_useInternalTexturePalette = false;
setTexturePool( pTexturePool );
}
else
{
// use internal texture palette
_useInternalTexturePalette = true;
setTexturePool( new TexturePool );
}
if (pMaterialPool)
{
// use external material palette, ignore internal
_useInternalMaterialPalette = false;
setMaterialPool( pMaterialPool );
}
else
{
// use internal material palette
_useInternalMaterialPalette = true;
setMaterialPool( new MaterialPool );
}
// no support for external light palettes
setLightPool( new LightPool );
// instances are always internally defined
setInstancePool( new InstancePool );
}
osg::Object* FltFile::readObject(const std::string& fileName)
{
return readNode(fileName);
}
osg::Node* FltFile::readNode(const std::string& fileName)
{
_directory = osgDB::getFilePath(fileName);
if (readModel(fileName))
{
// Convert record tree to osg scene graph
osg::Node* model = convert();
if (model)
{
// Store model origin in returned Node userData.
osg::ref_ptr<osgSim::GeographicLocation> loc = new osgSim::GeographicLocation;
double lat, lon;
getOrigin( lat, lon );
loc->set( lat, lon );
model->setUserData( loc.get() );
osg::notify(osg::INFO)<<"FltFile::readNode("<<fileName<<") lat="<<lat<<" lon="<<lon<<std::endl;
return model;
}
}
return NULL;
}
osg::Group* FltFile::convert()
{
ConvertFromFLT visit;
visit.setUseTextureAlphaForTransparancyBinning(getUseTextureAlphaForTransparancyBinning());
visit.setDoUnitsConversion(getDoUnitsConversion());
return visit.convert(getHeaderRecord());
}
// Read flight model (include externals)
bool FltFile::readModel(const std::string& fileName)
{
if (readFile(fileName))
{
readExternals();
return getHeaderRecord() ? true : false;
}
return false;
}
bool FltFile::readFile(const std::string& fileName)
{
FileInput fin;
if (!fin.open(fileName))
{
// havn't found file, look in OSGFILEPATH
std::string foundFileName = osgDB::findDataFile(fileName);
if (foundFileName.empty()) return false;
if (!fin.open(foundFileName)) return false;
}
osg::notify(osg::INFO) << "Loading " << fileName << " ... " << std::endl;
Record* pRec = fin.readCreateRecord(this);
if (pRec == NULL)
{
osg::notify(osg::WARN) << "File not found " << fileName << std::endl;
return false;
}
_headerRecord = (HeaderRecord*)pRec;
if (pRec->isPrimaryNode()) // Header
pRec->readLocalData(fin);// Read rest of file
fin.close();
return true;
}
#define REGISTER_FLT 1
// This class was originally scoped within FltFile::readExternals() function.
// Irix 7.3 compilers hork on this.
class ReadExternal : public RecordVisitor
{
public:
ReadExternal(FltFile* fltFile)
{
_pFltFile = fltFile;
setTraverseMode(RecordVisitor::TRAVERSE_ALL_CHILDREN);
}
virtual void apply(ExternalRecord& rec)
{
SExternalReference* pSExternal = (SExternalReference*)rec.getData();
if (pSExternal)
{
FltFile* pExternalFltFile = NULL;
ColorPool* pColorPool = NULL;
TexturePool* pTexturePool = NULL;
MaterialPool* pMaterialPool = NULL;
std::string filename(pSExternal->szPath);
osg::notify(osg::INFO) << "External=" << filename << std::endl;
if (rec.getFlightVersion() > 13)
{
if (pSExternal->dwFlags & ExternalRecord::COLOR_PALETTE_OVERRIDE)
pColorPool = NULL;
else
pColorPool = _pFltFile->getColorPool();
if (pSExternal->dwFlags & ExternalRecord::TEXTURE_PALETTE_OVERRIDE)
pTexturePool = NULL;
else
pTexturePool = _pFltFile->getTexturePool();
if (pSExternal->dwFlags & ExternalRecord::MATERIAL_PALETTE_OVERRIDE)
pMaterialPool = NULL;
else
pMaterialPool = _pFltFile->getMaterialPool();
}
#if REGISTER_FLT
pExternalFltFile = Registry::instance()->getFltFile(filename);
if (pExternalFltFile == NULL)
{
//Path for Nested external references
std::string filePath = osgDB::getFilePath(filename);
std::string pushAndPopPath;
//If absolute path
if( (filePath.length()>0 && filePath.find_first_of("/\\")==0) ||
(filePath.length()>2 && filePath.substr(1,1)==":" && filePath.find_first_of("/\\")==2) )
{
pushAndPopPath = filePath;
}
else
{
osgDB::FilePathList fpl = osgDB::getDataFilePathList();
pushAndPopPath = fpl.empty() ? "." : fpl.front();
if(pushAndPopPath.empty()) pushAndPopPath = ".";
pushAndPopPath += "/" + filePath;
}
osgDB::PushAndPopDataPath tmpfile(pushAndPopPath);
pExternalFltFile = new FltFile(pColorPool, pTexturePool, pMaterialPool);
pExternalFltFile->readModel(filename);
}
Registry::instance()->addFltFile(filename, pExternalFltFile);
#else
pExternalFltFile = new FltFile(pColorPool, pTexturePool, pMaterialPool);
pExternalFltFile->readModel(filename);
#endif
rec.setExternal(pExternalFltFile);
}
}
public:
FltFile* _pFltFile;
};
void FltFile::readExternals()
{
ReadExternal visitor(this);
_headerRecord->accept(visitor);
}
int FltFile::getFlightVersion() const
{
if (_headerRecord.get())
{
SHeader* pSHeader = (SHeader*)_headerRecord.get()->getData();
if (pSHeader)
return pSHeader->diFormatRevLev;
}
return 0;
}
void FltFile::getOrigin( double& latitude, double& longitude ) const
{
if (_headerRecord.get())
{
SHeader* pSHeader = (SHeader*)_headerRecord.get()->getData();
if (pSHeader)
{
latitude = pSHeader->Origin.x();
longitude = pSHeader->Origin.y();
}
}
}
std::string FltFile::getDesiredUnitsString() const
{
switch (_desiredUnits)
{
case ConvertToMeters:
return "ConvertToMeters";
break;
case ConvertToKilometers:
return "ConvertToKilometers";
break;
case ConvertToFeet:
return "ConvertToFeet";
break;
case ConvertToInches:
return "ConvertToInches";
break;
case ConvertToNauticalMiles:
return "ConvertToNauticalMiles";
break;
default:
return "Invalid";
break;
}
}