Integrated Brede Johansen's updates to flt loader.

This commit is contained in:
Robert Osfield
2001-12-04 16:03:10 +00:00
parent 3e940e0b33
commit d7ded2d90f
30 changed files with 1646 additions and 862 deletions

View File

@@ -29,24 +29,31 @@ ColorPaletteRecord::~ColorPaletteRecord()
// virtual
void ColorPaletteRecord::endian()
{
if (getSize() > sizeof(SOldColorPalette))
int flightVersion = getFlightVersion();
if (flightVersion > 13)
{
// TODO: May cause crash on win32
// It's only color names so we ignore
#if 0
SColorPalette* pSColor = (SColorPalette*)getData();
size_t nOffset = sizeof(SColorPalette);
if (nOffset < getSize())
if ((nOffset < getSize())
&& (flightVersion >= 1500))
{
int n = 0;
ENDIAN( pSColor->nNames );
while ((n++ < pSColor->nNames) && (nOffset < getSize()))
{
SColorName* pName = (SColorName*)((char*)getData())+nOffset;
SColorName* pName = (SColorName*)((char*)pSColor)+nOffset;
ENDIAN( pName->swSize );
ENDIAN( pName->nIndex );
nOffset += pName->swSize;
};
}
#endif
}
else // version 11, 12 & 13
{

View File

@@ -54,6 +54,7 @@ class ColorPaletteRecord : public AncillaryRecord
virtual Record* clone() const { return new ColorPaletteRecord(); }
virtual const char* className() const { return "ColorPaletteRecord"; }
virtual int classOpcode() const { return COLOR_PALETTE_OP; }
// virtual size_t sizeofData() const { return sizeof(SColorPalette); }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);

View File

@@ -36,12 +36,8 @@ void ExternalRecord::endian()
{
SExternalReference *pSExternal = (SExternalReference*)getData();
if (getSize() >= sizeof(SExternalReference))
if (getFlightVersion() > 13)
{
ENDIAN( pSExternal->diFlags );
}
else
{
pSExternal->diFlags = 0;
ENDIAN( pSExternal->dwFlags );
}
}

View File

@@ -15,18 +15,18 @@ namespace flt {
struct SExternalReference
{
SRecHeader RecHeader;
char szPath[200]; // 199 char ASCII Path; 0 terminates
char szPath[200]; // 199 char ASCII Path; 0 terminates
// version 11, 12 & 13 stops here!
uint8 swReserved[4]; // Reserved
int32 diFlags; // Flags (bits from left to right)
// 0 = Color Palette Override
// 1 = Material Palette Override
// 2 = Texture Palette Override
// 3 = Line Palette Override
// 4 = Sound Palette Override
// 5 = Light source Palette Override
// 6-31 Spare
// int16 iReserved; // Reserved
uint8 swReserved[4]; // Reserved
uint32 dwFlags; // Flags (bits from left to right)
// 0 = Color Palette Override
// 1 = Material Palette Override
// 2 = Texture Palette Override
// 3 = Line Palette Override
// 4 = Sound Palette Override
// 5 = Light source Palette Override
// 6-31 Spare
// int16 iReserved; // Reserved
};
@@ -47,6 +47,16 @@ class ExternalRecord : public PrimNodeRecord
FltFile* getExternal() { return _fltfile.get(); }
const std::string getFilename( void ) const { return std::string(getData()->szPath); }
enum Flag
{
COLOR_PALETTE_OVERRIDE = BIT31,
MATERIAL_PALETTE_OVERRIDE = BIT30,
TEXTURE_PALETTE_OVERRIDE = BIT29,
LINESTYLE_PALETTE_OVERRIDE = BIT28,
SOUND_PALETTE_OVERRIDE = BIT27,
LIGHTSOURCE_PALETTE_OVERRIDE = BIT26
};
protected:
virtual ~ExternalRecord();

View File

@@ -68,8 +68,8 @@ void FaceRecord::endian()
ENDIAN( pSFace->diIRMaterial );
ENDIAN( pSFace->wTransparency );
// Added after version 13
if (Registry::instance()->getVersion() > 13)
// Face record extended after version 13
if (getFltFile()->getFlightVersion() > 13)
{
ENDIAN( pSFace->dwFlags );
// ENDIAN( pSFace->PrimaryPackedColor );
@@ -93,12 +93,12 @@ bool FaceRecord::readLocalData(Input& fr)
Record* pRec;
if (!(pRec=fr.readCreateRecord())) return false;
if (!(pRec=fr.readCreateRecord(_pFltFile))) return false;
if (pRec->getOpcode() != PUSH_SUBFACE_OP)
return fr.rewindLast();
while ((pRec=fr.readCreateRecord()))
while ((pRec=fr.readCreateRecord(_pFltFile)))
{
if (pRec->getOpcode()==POP_SUBFACE_OP) return true;

View File

@@ -53,7 +53,8 @@ struct SFace
uint16 wTransparency; // Transparency
// = 0 opaque
// = 65535 for totally clear
// version 11, 12 & 13 stops here!
// version 11, 12 & 13 ends here!
uint8 swInfluenceLODGen; // LOD Generation Control
uint8 swLinestyle; // Linestyle Index
uint32 dwFlags; // Flags (bits from left to right)
@@ -70,9 +71,9 @@ struct SFace
// = 2 use face color and vertex normal
// = 3 use vertex color and vertex normal
uint8 Reserved1[7]; // Reserved
color32 PrimaryPackedColor; // Packed Color Primary (A, B, G, R)
color32 SecondaryPackedColor; // Packed Color Secondary (A, B, G, R)
uint8 Reserved1[7]; // Reserved
color32 PrimaryPackedColor; // Packed Color Primary (A, B, G, R)
color32 SecondaryPackedColor; // Packed Color Secondary (A, B, G, R)
int16 iTextureMapIndex; // Texture mapping index
int16 iReserved2;
uint32 dwPrimaryColorIndex;

View File

@@ -11,6 +11,7 @@
#include <osg/Notify>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <string>
@@ -23,44 +24,42 @@ FltFile::FltFile(
TexturePool* pTexturePool,
MaterialPool* pMaterialPool)
{
_pHeaderRecord = NULL;
if (pColorPool)
{
// use external color palette, ignore internal
_useColorPalette = false;
_useInternalColorPalette = false;
setColorPool( pColorPool );
}
else
{
// use internal color palette
_useColorPalette = true;
_useInternalColorPalette = true;
setColorPool( new ColorPool );
}
if (pTexturePool)
{
// use external texture palette, ignore internal
_useTexturePalette = false;
_useInternalTexturePalette = false;
setTexturePool( pTexturePool );
}
else
{
// use internal texture palette
_useTexturePalette = true;
_useInternalTexturePalette = true;
setTexturePool( new TexturePool );
}
if (pMaterialPool)
{
// use external material palette, ignore internal
_useMaterialPalette = false;
_useInternalMaterialPalette = false;
setMaterialPool( pMaterialPool );
}
else
{
// use internal material palette
_useMaterialPalette = true;
_useInternalMaterialPalette = true;
setMaterialPool( new MaterialPool );
}
}
@@ -74,46 +73,44 @@ osg::Object* FltFile::readObject(const std::string& fileName)
osg::Node* FltFile::readNode(const std::string& fileName)
{
osg::Node* node = NULL;
Record* pRootRec = readModel(fileName);
_directory = osgDB::getFilePath(fileName);
if (pRootRec == NULL)
return NULL;
if (readModel(fileName))
{
// Convert record tree to osg scene graph
return convert();
}
// Convert record tree to osg scene graph
node = convert();
pRootRec->unref(); // delete record tree
return node;
return NULL;
}
osg::Node* FltFile::convert()
{
ConvertFromFLT visit(this);
ConvertFromFLT visit;
return visit.convert(getHeaderRecord());
}
// Read flight model (include externals)
Record* FltFile::readModel(const std::string& fileName)
bool FltFile::readModel(const std::string& fileName)
{
Record* pRec = readFile(fileName);
if (pRec == NULL) return NULL;
readExternals(pRec);
return pRec;
if (readFile(fileName))
{
readExternals();
return getHeaderRecord() ? true : false;
}
return false;
}
Record* FltFile::readFile(const std::string& fileName)
bool FltFile::readFile(const std::string& fileName)
{
FileInput fin;
if (!fin.open(fileName))
{
// ok havn't found file, resort to using findFile...
// havn't found file, look in OSGFILEPATH
char* newFileName = osgDB::findFile(fileName.c_str());
if (!newFileName) return NULL;
@@ -122,99 +119,99 @@ Record* FltFile::readFile(const std::string& fileName)
osg::notify(osg::INFO) << "Loading " << fileName << " ... " << endl;
Record* pRec = fin.readCreateRecord();
_pHeaderRecord = pRec;
Record* pRec = fin.readCreateRecord(this);
if (pRec == NULL)
{
osg::notify(osg::WARN) << "File not found " << fileName << endl;
return NULL;
return false;
}
_headerRecord = (HeaderRecord*)pRec;
if (pRec->isPrimaryNode()) // Header
pRec->readLocalData(fin);// Read rest of file
fin.close();
return pRec;
return true;
}
#define REGISTER_FLT 1
class ReadExternal : public RecordVisitor
void FltFile::readExternals()
{
public:
ReadExternal(FltFile* fltFile)
{
_parentFltFile = fltFile;
setTraverseMode(RecordVisitor::TRAVERSE_ALL_CHILDREN);
}
virtual void apply(ExternalRecord& rec)
{
SExternalReference* pSExternal = (SExternalReference*)rec.getData();
if (pSExternal)
{
FltFile* flt = NULL;
ColorPool* pColorPool = NULL;
TexturePool* pTexturePool = NULL;
MaterialPool* pMaterialPool = NULL;
std::string filename(pSExternal->szPath);
osg::notify(osg::INFO) << "External=" << filename << endl;
if (_parentFltFile && (_parentFltFile->getFlightVersion() > 13))
{
if (pSExternal->diFlags & BIT0)
pColorPool = _parentFltFile->getColorPool();
if (pSExternal->diFlags & BIT2)
pTexturePool = _parentFltFile->getTexturePool();
if (pSExternal->diFlags & BIT1)
pMaterialPool = _parentFltFile->getMaterialPool();
}
#if REGISTER_FLT
flt = Registry::instance()->getFltFile(filename);
if (flt == NULL)
{
flt = new FltFile(pColorPool, pTexturePool, pMaterialPool);
flt->readModel(filename);
}
Registry::instance()->addFltFile(filename, flt);
#else
flt = new FltFile(pColorPool, pTexturePool, pMaterialPool);
flt->readModel(filename);
#endif
rec.setExternal(flt);
}
}
public:
FltFile* _parentFltFile;
};
void FltFile::readExternals(Record* pRec)
{
if (pRec)
class ReadExternal : public RecordVisitor
{
ReadExternal visitor(this);
pRec->accept(visitor);
}
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 << 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)
{
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;
};
ReadExternal visitor(this);
_headerRecord->accept(visitor);
}
int FltFile::getFlightVersion()
{
if (_pHeaderRecord)
if (_headerRecord.get())
{
SHeader* pSHeader = (SHeader*)_pHeaderRecord->getData();
SHeader* pSHeader = (SHeader*)_headerRecord.get()->getData();
if (pSHeader)
return pSHeader->diFormatRevLev;
}

View File

@@ -29,8 +29,7 @@ class FltFile : public osg::Referenced
virtual osg::Object* readObject(const std::string& fileName);
virtual osg::Node* readNode(const std::string& fileName);
osg::Node* convert();
Record* getHeaderRecord() { return _pHeaderRecord; }
Record* readModel(const std::string& fileName);
bool readModel(const std::string& fileName);
ColorPool* getColorPool() { return _colorPool.get(); }
TexturePool* getTexturePool() { return _texturePool.get(); }
@@ -40,27 +39,30 @@ class FltFile : public osg::Referenced
void setTexturePool(TexturePool* texturePool) { _texturePool = texturePool; }
void setMaterialPool(MaterialPool* materialPool){ _materialPool = materialPool; }
inline const bool useColorPalette() const { return _useColorPalette; }
inline const bool useTexturePalette() const { return _useTexturePalette; }
inline const bool useMaterialPalette() const { return _useMaterialPalette; }
inline const bool useInternalColorPalette() const { return _useInternalColorPalette; }
inline const bool useInternalTexturePalette() const { return _useInternalTexturePalette; }
inline const bool useInternalMaterialPalette() const { return _useInternalMaterialPalette; }
int getFlightVersion();
inline HeaderRecord* getHeaderRecord() { return _headerRecord.get(); }
protected:
virtual ~FltFile() {}
Record* readFile(const std::string& fileName);
void readExternals(Record* pRec);
bool readFile(const std::string& fileName);
void readExternals();
private:
Record* _pHeaderRecord;
osg::ref_ptr<HeaderRecord> _headerRecord;
bool _useColorPalette;
bool _useTexturePalette;
bool _useMaterialPalette;
bool _useInternalColorPalette;
bool _useInternalTexturePalette;
bool _useInternalMaterialPalette;
std::string _directory;
osg::ref_ptr<ColorPool> _colorPool;
osg::ref_ptr<TexturePool> _texturePool;
osg::ref_ptr<MaterialPool> _materialPool;

View File

@@ -8,9 +8,6 @@
#include "FltFile.h"
#include "Pool.h"
#include "opcodes.h"
#include "VertexPoolRecords.h"
#include "OldVertexRecords.h"
#include "MaterialPaletteRecord.h"
#include "GeoSetBuilder.h"
#include <osg/Object>
@@ -35,323 +32,91 @@ using namespace flt;
////////////////////////////////////////////////////////////////////
//
// TmpGeoSet
// DynGeoSet
//
////////////////////////////////////////////////////////////////////
// GeoSet with dynamic vertex size.
TmpGeoSet::TmpGeoSet(FltFile* pFltFile)
#define APPEND_DynGeoSet_List(list) \
if (source->list.size() > 0) \
list.insert(list.end(), \
source->list.begin(), source->list.end());
void DynGeoSet::append(DynGeoSet* source)
{
_geoSet = new osg::GeoSet;
_geoSet->setStateSet( new osg::StateSet );
_colorPool = pFltFile->getColorPool();
_texturePool = pFltFile->getTexturePool();
_materialPool = pFltFile->getMaterialPool();
APPEND_DynGeoSet_List(_primLenList)
APPEND_DynGeoSet_List(_coordList)
APPEND_DynGeoSet_List(_normalList)
APPEND_DynGeoSet_List(_colorList)
APPEND_DynGeoSet_List(_tcoordList)
}
osg::GeoSet* TmpGeoSet::createOsgGeoSet()
#define VERIFY_DynGeoSet_Binding(binding,list) \
switch (binding) \
{ \
case osg::GeoSet::BIND_PERVERTEX: \
if (list.size() < _coordList.size()) { \
binding = osg::GeoSet::BIND_OFF; \
list.clear(); } \
break; \
case osg::GeoSet::BIND_PERPRIM: \
if (list.size() < _primLenList.size()) { \
binding = osg::GeoSet::BIND_OFF; \
list.clear(); } \
break; \
case osg::GeoSet::BIND_OVERALL: \
if (list.size() < 1) { \
binding = osg::GeoSet::BIND_OFF; \
list.clear(); } \
break; \
}
void DynGeoSet::setBinding()
{
int prims = _primLenList.size();
int indices = _vertexRecList.size();
VERIFY_DynGeoSet_Binding(_normal_binding, _normalList)
VERIFY_DynGeoSet_Binding(_color_binding, _colorList)
VERIFY_DynGeoSet_Binding(_texture_binding, _tcoordList)
if (prims==0 || indices==0)
return NULL;
// Set bindings
setNormalBinding(_normal_binding);
setColorBinding(_color_binding);
setTextureBinding(_texture_binding);
osg::GeoSet* gset = getGeoSet();
gset->setNumPrims(prims);
// prim lengths
switch( gset->getPrimType() )
osg::StateSet* stateset = getStateSet();
if (stateset)
{
case osg::GeoSet::QUAD_STRIP :
case osg::GeoSet::FLAT_TRIANGLE_FAN :
case osg::GeoSet::TRIANGLE_FAN :
case osg::GeoSet::LINE_LOOP :
case osg::GeoSet::LINE_STRIP :
case osg::GeoSet::FLAT_LINE_STRIP :
case osg::GeoSet::TRIANGLE_STRIP :
case osg::GeoSet::FLAT_TRIANGLE_STRIP :
case osg::GeoSet::POLYGON :
{
int *lens = new int[prims];
gset->setPrimLengths( lens );
for (int n=0; n < prims; n++)
lens[n] = _primLenList[n];
}
break;
if (_normal_binding == osg::GeoSet::BIND_OFF)
stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
}
// create osg compatible buffers
gset->setCoords(new osg::Vec3[indices]);
if (gset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
gset->setColors(new osg::Vec4[indices]);
if (gset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX)
gset->setNormals(new osg::Vec3[indices]);
if (gset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
gset->setTextureCoords(new osg::Vec2[indices]);
// Copy vertices across
{
int index;
VertexRecList::iterator itr;
for(index=0, itr=_vertexRecList.begin();
itr!=_vertexRecList.end();
++index, ++itr)
{
setVertex(gset, index, itr->get());
}
}
return gset;
}
void TmpGeoSet::setVertex(osg::GeoSet* gset, int index, Record* vertex)
bool DynGeoSet::setLists()
{
osg::Vec3* coords = gset->getCoords();
osg::Vec4* colors = gset->getColors();
osg::Vec3* normals = gset->getNormals();
osg::Vec2* texuv = gset->getTextureCoords();
switch(vertex->getOpcode())
if ((_primLenList.size() > 0) && (_coordList.size() > 0))
{
case VERTEX_C_OP:
{
SVertex* pVert = (SVertex*)vertex->getData();
GeoSet::setPrimLengths(_primLenList.begin());
GeoSet::setCoords(_coordList.begin());
coords[index].set(
(float)pVert->Coord.x(),
(float)pVert->Coord.y(),
(float)pVert->Coord.z());
if ((_normalList.size() > 0)
&& (getNormalBinding() != osg::GeoSet::BIND_OFF))
GeoSet::setNormals(_normalList.begin());
if (gset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
{
if (pVert->swFlags & V_NO_COLOR_BIT)
colors[index] = osg::Vec4(1,1,1,1);
else
{
if (pVert->swFlags & V_PACKED_COLOR_BIT)
colors[index] = pVert->PackedColor.get();
else
{
ColorPool* pColorPool = _colorPool.get();
colors[index] = pColorPool->getColor(pVert->dwVertexColorIndex);
}
}
}
}
break;
if ((_colorList.size() > 0)
&& (getColorBinding() != osg::GeoSet::BIND_OFF))
GeoSet::setColors(_colorList.begin());
case VERTEX_CN_OP:
{
SNormalVertex* pVert = (SNormalVertex*)vertex->getData();
if ((_tcoordList.size() > 0)
&& (getTextureBinding() != osg::GeoSet::BIND_OFF))
GeoSet::setTextureCoords(_tcoordList.begin());
coords[index].set(
(float)pVert->Coord.x(),
(float)pVert->Coord.y(),
(float)pVert->Coord.z());
if (gset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX)
{
normals[index].set(
(float)pVert->Normal.x(),
(float)pVert->Normal.y(),
(float)pVert->Normal.z());
normals[index].normalize();
}
if (gset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
{
if (pVert->swFlags & V_NO_COLOR_BIT)
colors[index] = osg::Vec4(1,1,1,1);
else
{
if (pVert->swFlags & V_PACKED_COLOR_BIT)
colors[index] = pVert->PackedColor.get();
else
{
ColorPool* pColorPool = _colorPool.get();
colors[index] = pColorPool->getColor(pVert->dwVertexColorIndex);
}
}
}
}
break;
case VERTEX_CNT_OP:
{
SNormalTextureVertex* pVert = (SNormalTextureVertex*)vertex->getData();
coords[index].set(
(float)pVert->Coord.x(),
(float)pVert->Coord.y(),
(float)pVert->Coord.z());
if (gset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX)
{
normals[index].set(
(float)pVert->Normal.x(),
(float)pVert->Normal.y(),
(float)pVert->Normal.z());
normals[index].normalize();
}
if (gset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
{
texuv[index].set(
(float)pVert->Texture.x(),
(float)pVert->Texture.y());
}
if (gset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
{
if (pVert->swFlags & V_NO_COLOR_BIT)
colors[index] = osg::Vec4(1,1,1,1);
else
{
if (pVert->swFlags & V_PACKED_COLOR_BIT)
colors[index] = pVert->PackedColor.get();
else
{
ColorPool* pColorPool = _colorPool.get();
colors[index] = pColorPool->getColor(pVert->dwVertexColorIndex);
}
}
}
}
break;
case VERTEX_CT_OP:
{
STextureVertex* pVert = (STextureVertex*)vertex->getData();
coords[index].set(
(float)pVert->Coord.x(),
(float)pVert->Coord.y(),
(float)pVert->Coord.z());
if (gset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
{
texuv[index].set(
(float)pVert->Texture.x(),
(float)pVert->Texture.y());
}
if (gset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
{
osg::Vec4* colors = gset->getColors();
if (pVert->swFlags & V_NO_COLOR_BIT)
colors[index] = osg::Vec4(1,1,1,1);
else
{
if (pVert->swFlags & V_PACKED_COLOR_BIT)
colors[index] = pVert->PackedColor.get();
else
{
ColorPool* pColorPool = _colorPool.get();
colors[index] = pColorPool->getColor(pVert->dwVertexColorIndex);
}
}
}
}
break;
case OLD_VERTEX_OP:
{
SOldVertex* pVert = (SOldVertex*)vertex->getData();
coords[index].set(
(float)pVert->v[0],
(float)pVert->v[1],
(float)pVert->v[2]);
if ((gset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
&& (vertex->getSize() >= sizeof(SOldVertex)))
{
texuv[index].set(
(float)pVert->t[0],
(float)pVert->t[1]);
}
}
break;
case OLD_VERTEX_COLOR_OP:
{
SOldVertexColor* pVert = (SOldVertexColor*)vertex->getData();
coords[index].set(
(float)pVert->v[0],
(float)pVert->v[1],
(float)pVert->v[2]);
if (gset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
{
osg::Vec4* colors = gset->getColors();
ColorPool* pColorPool = _colorPool.get();
if (pColorPool)
colors[index] = pColorPool->getColor(pVert->color_index);
else
colors[index] = osg::Vec4(1,1,1,1);
}
if ((gset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
&& (vertex->getSize() >= sizeof(SOldVertexColor)))
{
texuv[index].set(
(float)pVert->t[0],
(float)pVert->t[1]);
}
}
break;
case OLD_VERTEX_COLOR_NORMAL_OP:
{
SOldVertexColorNormal* pVert = (SOldVertexColorNormal*)vertex->getData();
coords[index].set(
(float)pVert->v[0],
(float)pVert->v[1],
(float)pVert->v[2]);
if (gset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX)
{
normals[index].set(
(float)pVert->n[0] / (1<<30), // =pow(2,30)
(float)pVert->n[1] / (1<<30),
(float)pVert->n[2] / (1<<30));
normals[index].normalize();
}
if (gset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
{
osg::Vec4* colors = gset->getColors();
ColorPool* pColorPool = _colorPool.get();
if (pColorPool)
colors[index] = pColorPool->getColor(pVert->color_index);
else
colors[index] = osg::Vec4(1,1,1,1);
}
if ((gset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
&& (vertex->getSize() >= sizeof(SOldVertexColorNormal)))
{
texuv[index].set(
(float)pVert->t[0],
(float)pVert->t[1]);
}
}
break;
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
@@ -363,108 +128,77 @@ void TmpGeoSet::setVertex(osg::GeoSet* gset, int index, Record* vertex)
// OpenFlight don't save data in GeoSets. This class tries to find
// existing GeoSets with matching state before creating a new GeoSet.
GeoSetBuilder::GeoSetBuilder(FltFile* pFltFile)
GeoSetBuilder::GeoSetBuilder(osg::Geode* geode)
{
_pFltFile = pFltFile;
_geode = geode;
initPrimData();
}
void GeoSetBuilder::initPrimData()
{
_tmpGeoSet = new TmpGeoSet(_pFltFile.get());
_dynGeoSet = new DynGeoSet;
_dynGeoSet->setStateSet(new osg::StateSet);
}
// Convert flt::TmpGeoSet's to osg::GeoSet's and add to osg::Geode.
// If geode parameter is NULL create new.
// If geode created inside this function and no osg::GeoSet's
// added free geode.
osg::Geode* GeoSetBuilder::createOsgGeoSets(osg::Geode* geode)
osg::Geode* GeoSetBuilder::createOsgGeoSets()
{
bool bInternalGeodeAllocation = false;
if (geode == NULL)
{
geode = new osg::Geode;
bInternalGeodeAllocation = true;
}
for(TmpGeoSetList::iterator itr=_tmpGeoSetList.begin();
itr!=_tmpGeoSetList.end();
for(DynGeoSetList::iterator itr=_dynGeoSetList.begin();
itr!=_dynGeoSetList.end();
++itr)
{
osg::GeoSet* gset = (*itr)->createOsgGeoSet();
if (gset)
geode->addDrawable(gset);
DynGeoSet* dgset = itr->get();
if (dgset)
{
int prims = dgset->primLenListSize();
if (prims > 0)
{
dgset->setLists();
dgset->setNumPrims(prims);
_geode.get()->addDrawable(dgset);
}
}
}
if (bInternalGeodeAllocation && (geode->getNumDrawables() == 0))
{
geode->unref();
return NULL;
}
return geode;
return _geode.get();
}
bool GeoSetBuilder::addPrimitive()
{
osg::GeoSet* geoset = getGeoSet();
DynGeoSet* dgset = getDynGeoSet(); // This is the new geoset we want to add
if (geoset->getPrimType() == osg::GeoSet::NO_TYPE)
geoset->setPrimType(findPrimType(numberOfVertices()));
if (dgset->getPrimType() == osg::GeoSet::NO_TYPE)
dgset->setPrimType(findPrimType(dgset->coordListSize()));
// Still no primitive type?
if (geoset->getPrimType() == osg::GeoSet::NO_TYPE)
if (dgset->getPrimType() == osg::GeoSet::NO_TYPE)
return false;
TmpGeoSet* match = findMatchingGeoSet();
dgset->setBinding();
DynGeoSet* match = findMatchingGeoSet();
if (match)
// append vertices and prim length to match
match->addVertices( _tmpGeoSet.get() );
match->append(dgset);
else
// add new GeoSet+StateSet compination
_tmpGeoSetList.push_back(_tmpGeoSet.get());
initPrimData(); // initialize _tmpGeoSet
_dynGeoSetList.push_back(dgset);
initPrimData(); // initialize _dynGeoSet
return true;
}
TmpGeoSet* GeoSetBuilder::findMatchingGeoSet()
DynGeoSet* GeoSetBuilder::findMatchingGeoSet()
{
osg::GeoSet* geoSet = getGeoSet();
osg::StateSet* stateSet = geoSet->getStateSet();
for(TmpGeoSetList::iterator itr=_tmpGeoSetList.begin();
itr!=_tmpGeoSetList.end();
DynGeoSet* new_dgset = getDynGeoSet();
for(DynGeoSetList::iterator itr=_dynGeoSetList.begin();
itr!=_dynGeoSetList.end();
++itr)
{
TmpGeoSet* tmpgeoset = itr->get();
osg::GeoSet* gset = tmpgeoset->getGeoSet();
osg::StateSet* sset = gset->getStateSet();
// Do we have a match?
if ((geoSet->getPrimType() == gset->getPrimType())
&& (geoSet->getColorBinding() == gset->getColorBinding())
&& (geoSet->getNormalBinding() == gset->getNormalBinding())
&& (geoSet->getTextureBinding() == gset->getTextureBinding())
&& (stateSet->compare(*sset, true) == 0))
{
if (geoSet->getColorBinding() == osg::GeoSet::BIND_OVERALL)
{
osg::Vec4* col1 = geoSet->getColors();
osg::Vec4* col2 = gset->getColors();
if (*col1 != *col2)
return NULL;
}
return tmpgeoset;
}
DynGeoSet* dgset = itr->get();
if (*new_dgset == *dgset)
return dgset;
}
return NULL;
@@ -473,28 +207,16 @@ TmpGeoSet* GeoSetBuilder::findMatchingGeoSet()
osg::GeoSet::PrimitiveType GeoSetBuilder::findPrimType(const int nVertices)
{
osg::GeoSet::PrimitiveType primtype = osg::GeoSet::NO_TYPE;
switch (nVertices)
{
case 1:
primtype = osg::GeoSet::POINTS;
break;
case 2:
primtype = osg::GeoSet::LINES;
break;
case 3:
primtype = osg::GeoSet::TRIANGLES;
break;
case 4:
primtype = osg::GeoSet::QUADS;
break;
default:
if (nVertices >= 5) primtype = osg::GeoSet::POLYGON;
break;
case 1: return osg::GeoSet::POINTS;
case 2: return osg::GeoSet::LINES;
case 3: return osg::GeoSet::TRIANGLES;
case 4: return osg::GeoSet::QUADS;
}
return primtype;
if (nVertices >= 5) return osg::GeoSet::POLYGON;
return osg::GeoSet::NO_TYPE;
}

View File

@@ -2,11 +2,11 @@
#define __FLT_GEOSETBUILDER_H
#include <osg/ref_ptr>
#include <osg/Referenced>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/GeoSet>
#include <osg/Geode>
#include <osg/Material>
#include <osg/StateSet>
@@ -20,63 +20,85 @@ class Record;
class TmpGeoSet;
////////////////////////////////////////////////////////////////////
//
// TmpGeoSet
// DynGeoSet
//
////////////////////////////////////////////////////////////////////
#if 0
# define COMPARE_DynGeoSet_Parameter(parameter) \
if (parameter<rhs.parameter) return -1; \
if (rhs.parameter<parameter) return 1;
#else
# define COMPARE_DynGeoSet_Parameter(parameter) \
if (parameter != rhs.parameter) return -1;
#endif
/** TmpGeoSet - Temporary GeoSet with dynamic vertex array.
/** DynGeoSet - Dynamic GeoSet.
* Problem: osg::GeoSet use C arrays (static size) for coordinates,
* normals, colors and texture coordinates.
*/
class TmpGeoSet : public osg::Referenced
class DynGeoSet : public osg::GeoSet
{
public:
TmpGeoSet(FltFile* pFltFile);
virtual ~TmpGeoSet() {};
virtual osg::Object* clone() const { return new DynGeoSet(); }
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const DynGeoSet*>(obj)!=NULL; }
virtual const char* className() const { return "DynGeoSet"; }
void addVertex(Record* vertexRec) { _vertexRecList.push_back(vertexRec); }
void addPrimLen(int len) { _primLenList.push_back(len); }
// Append vertices from other TmpGeoSet
void addVertices(TmpGeoSet* source)
int compare(const DynGeoSet& rhs) const
{
_vertexRecList.insert(_vertexRecList.end(),
source->_vertexRecList.begin(), source->_vertexRecList.end());
_primLenList.insert(_primLenList.end(),
source->_primLenList.begin(), source->_primLenList.end());
COMPARE_DynGeoSet_Parameter(_primtype)
COMPARE_DynGeoSet_Parameter(_color_binding)
COMPARE_DynGeoSet_Parameter(_normal_binding)
COMPARE_DynGeoSet_Parameter(_texture_binding)
if ((_color_binding == osg::GeoSet::BIND_OVERALL)
&& (_colorList.size() >= 1) && (rhs._colorList.size() >= 1)
&& (_colorList[0] != rhs._colorList[0]))
return -1;
return getStateSet()->compare(*rhs.getStateSet(), true);
}
bool operator < (const DynGeoSet& rhs) const { return compare(rhs)<0; }
bool operator == (const DynGeoSet& rhs) const { return compare(rhs)==0; }
bool operator != (const DynGeoSet& rhs) const { return compare(rhs)!=0; }
inline const int numberOfVertices() const { return _vertexRecList.size(); }
inline osg::GeoSet* getGeoSet() { return _geoSet.get(); }
inline const osg::GeoSet* getGeoSet() const { return _geoSet.get(); }
inline void addPrimLen(const int len) { _primLenList.push_back(len); }
inline void addCoord(const osg::Vec3& coord) { _coordList.push_back(coord); }
inline void addNormal(const osg::Vec3& normal) { _normalList.push_back(normal); }
inline void addColor(const osg::Vec4& color) { _colorList.push_back(color); }
inline void addTCoord(const osg::Vec2& tcoord) { _tcoordList.push_back(tcoord); }
// Create complete osg::GeoSet.
osg::GeoSet* createOsgGeoSet();
void append(DynGeoSet* source);
void setBinding();
bool setLists();
inline const int primLenListSize() const { return _primLenList.size(); }
inline const int coordListSize() const { return _coordList.size(); }
inline const int normalListSize() const { return _normalList.size(); }
inline const int colorListSize() const { return _colorList.size(); }
inline const int tcoordListSize() const { return _tcoordList.size(); }
private:
typedef std::vector<osg::ref_ptr<Record> > VertexRecList;
typedef std::vector<int> PrimLenList;
void setVertex(osg::GeoSet* gset, int index, Record* vertex);
osg::ref_ptr<osg::GeoSet> _geoSet;
PrimLenList _primLenList;
VertexRecList _vertexRecList;
osg::ref_ptr<ColorPool> _colorPool;
osg::ref_ptr<TexturePool> _texturePool;
osg::ref_ptr<MaterialPool> _materialPool;
typedef std::vector<int> PrimLenList;
typedef std::vector<osg::Vec3> CoordList;
typedef std::vector<osg::Vec3> NormalList;
typedef std::vector<osg::Vec4> ColorList;
typedef std::vector<osg::Vec2> TcoordList;
PrimLenList _primLenList;
CoordList _coordList;
NormalList _normalList;
ColorList _colorList;
TcoordList _tcoordList;
};
////////////////////////////////////////////////////////////////////
//
// GeoSetBuilder
@@ -91,32 +113,28 @@ class GeoSetBuilder
{
public:
GeoSetBuilder(FltFile* pFltFile);
GeoSetBuilder(osg::Geode* geode);
virtual ~GeoSetBuilder() {}
void addVertex(Record* vertex) { _tmpGeoSet.get()->addVertex(vertex); }
void addPrimLen(int len) { _tmpGeoSet.get()->addPrimLen(len); }
bool addPrimitive();
osg::Geode* createOsgGeoSets(osg::Geode* geode=NULL);
osg::Geode* createOsgGeoSets();
inline osg::GeoSet* getGeoSet() { return _tmpGeoSet.get()->getGeoSet(); }
inline const osg::GeoSet* getGeoSet() const { return _tmpGeoSet.get()->getGeoSet(); }
const int numberOfVertices() const { return _tmpGeoSet.get()->numberOfVertices(); }
inline DynGeoSet* getDynGeoSet() { return _dynGeoSet.get(); }
inline const DynGeoSet* getDynGeoSet() const { return _dynGeoSet.get(); }
protected:
void initPrimData();
TmpGeoSet* findMatchingGeoSet();
DynGeoSet* findMatchingGeoSet();
osg::GeoSet::PrimitiveType findPrimType(const int nVertices);
private:
osg::ref_ptr<FltFile> _pFltFile;
osg::ref_ptr<TmpGeoSet> _tmpGeoSet;
osg::ref_ptr<osg::Geode> _geode;
osg::ref_ptr<DynGeoSet> _dynGeoSet;
typedef std::vector<osg::ref_ptr<TmpGeoSet> > TmpGeoSetList;
TmpGeoSetList _tmpGeoSetList;
typedef std::vector<osg::ref_ptr<DynGeoSet> > DynGeoSetList;
DynGeoSetList _dynGeoSetList;
};

View File

@@ -117,8 +117,6 @@ void HeaderRecord::endian()
ENDIAN( pHeader->dfLambertUpperLat );
ENDIAN( pHeader->dfLambertLowerLat );
ENDIAN( pHeader->iNextLightSource );
Registry::instance()->setVersion(pHeader->diFormatRevLev);
}

View File

@@ -99,6 +99,15 @@ class HeaderRecord : public PrimNodeRecord
SHeader* getData() const { return (SHeader*)_pData; }
virtual const std::string getName( void ) const { return std::string(getData()->szIdent); }
enum CoordUnit
{
METERS = 0,
KILOMETERS = 1,
FEET = 4,
INCHES = 5,
NAUTICAL_MILES = 8
};
protected:
virtual ~HeaderRecord();

View File

@@ -23,6 +23,7 @@ using namespace std;
using namespace flt;
FileInput::FileInput()
{
_init();
@@ -165,7 +166,7 @@ SRecHeader* FileInput::readRecord()
}
Record* Input::readCreateRecord()
Record* Input::readCreateRecord(FltFile* pFltFile)
{
SRecHeader* pData = readRecord();
@@ -194,6 +195,8 @@ Record* Input::readCreateRecord()
return NULL;
}
pRec->_pFltFile = pFltFile;
#if 0
osg::notify(osg::ALWAYS) << "class=" << pRec->className();
osg::notify(osg::ALWAYS) << " op=" << pRec->getOpcode();

View File

@@ -20,6 +20,7 @@ namespace flt {
class Record;
class FltFile;
class Input
@@ -33,7 +34,7 @@ class Input
virtual bool rewindLast() = 0;
virtual long offset() = 0;
Record* readCreateRecord();
Record* readCreateRecord(FltFile* pFltFile);
protected:

View File

@@ -38,6 +38,7 @@ C++FILES = \
Pool.cpp\
TextureMappingPaletteRecord.cpp\
ReaderWriterFLT.cpp\
ReaderWriterATTR.cpp\
# PointLight.cpp\

View File

@@ -61,7 +61,7 @@ ColorPool::ColorName* ColorPool::getColorName(int nIndex)
////////////////////////////////////////////////////////////////////
osg::Texture* TexturePool::getTexture(int nIndex)
osg::StateSet* TexturePool::getTexture(int nIndex)
{
TexturePaletteMap::iterator fitr = _textureMap.find(nIndex);
if (fitr != _textureMap.end())
@@ -71,9 +71,9 @@ osg::Texture* TexturePool::getTexture(int nIndex)
}
void TexturePool::addTexture(int nIndex, osg::Texture* osgTexture)
void TexturePool::addTexture(int nIndex, osg::StateSet* stateset)
{
_textureMap[nIndex] = osgTexture;
_textureMap[nIndex] = stateset;
}

View File

@@ -8,12 +8,11 @@
#include <osg/Vec4>
#include <osg/Texture>
#include <osg/Material>
#include <osg/StateSet>
#include <string>
#include <algorithm>
#include <map>
//#include <vector>
namespace flt {
@@ -59,8 +58,8 @@ class TexturePool : public osg::Referenced
TexturePool() {}
osg::Texture* getTexture(int nIndex);
void addTexture(int nIndex, osg::Texture* osgTexture);
osg::StateSet* getTexture(int nIndex);
void addTexture(int nIndex, osg::StateSet* stateset);
protected :
@@ -68,7 +67,7 @@ class TexturePool : public osg::Referenced
private :
typedef std::map<int,osg::ref_ptr<osg::Texture> > TexturePaletteMap;
typedef std::map<int,osg::ref_ptr<osg::StateSet> > TexturePaletteMap;
TexturePaletteMap _textureMap;
};

View File

@@ -0,0 +1,713 @@
//
// OpenFlight<68> texture attribute loader for Open Scene Graph
//
// Copyright (C) 2001 Brede Johansen
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
// The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
// real-time rendering of large 3D photo-realistic models.
// The OSG homepage is http://www.openscenegraph.org/
//
// MultiGen, OpenFlight, and Flight Format are registered trademarks of MultiGen Inc.
//
#include <stdio.h>
#include <string.h>
#include <osg/Notify>
#include <osg/TexEnv>
#include <osg/Texture>
#include <osg/StateSet>
#include <osg/GL>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <iostream>
#include <fstream>
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef signed long int32;
typedef unsigned long uint32;
typedef float float32;
typedef double float64;
#define READ(DST) readField(file, (void*)&(DST), sizeof(DST))
static int isLittleEndianMachine()
{
int a = 1;
return (int)(*(char*)&a);
}
static void endian2(void* pSrc, int nSrc, void* pDst)
{
if (nSrc == 2)
{
short tmp1;
tmp1 = *(short *)pSrc;
tmp1 = (tmp1 << 8) | ((tmp1 >> 8) & 0xff);
*(short *)pDst = tmp1;
}
else if (nSrc == 4)
{
long tmp1;
tmp1 = *(long *)pSrc;
tmp1 = (tmp1 << 24) | ((tmp1 << 8) & 0xff0000) | ((tmp1 >> 8) & 0xff00) | ((tmp1 >> 24) & 0xff);
*(long *)pDst = tmp1;
}
else if (nSrc == 8)
{
long tmp1, tmp2;
tmp1 = *(long *)pSrc;
tmp2 = *(1 + (long *)pSrc);
tmp1 = (tmp1 << 24) | ((tmp1 << 8) & 0xff0000) | ((tmp1 >> 8) & 0xff00) | ((tmp1 >> 24) & 0xff);
tmp2 = (tmp2 << 24) | ((tmp2 << 8) & 0xff0000) | ((tmp2 >> 8) & 0xff00) | ((tmp2 >> 24) & 0xff);
*(long *)pDst = tmp2;
*(1 + (long *)pDst) = tmp1;
}
}
using namespace osg;
class Attr
{
public :
enum MinFilterMode {
MIN_FILTER_POINT = 0,
MIN_FILTER_BILINEAR = 1,
MIN_FILTER_MIPMAP = 2, // (Obsolete)
MIN_FILTER_MIPMAP_POINT = 3,
MIN_FILTER_MIPMAP_LINEAR = 4,
MIN_FILTER_MIPMAP_BILINEAR = 5,
MIN_FILTER_MIPMAP_TRILINEAR = 6,
MIN_FILTER_NONE = 7,
MIN_FILTER_BICUBIC = 8,
MIN_FILTER_BILINEAR_GEQUAL = 8,
MIN_FILTER_BILINEAR_LEQUAL = 10,
MIN_FILTER_BICUBIC_GEQUAL = 11,
MIN_FILTER_BICUBIC_LEQUAL = 12
};
enum MagFilterMode {
MAG_FILTER_POINT = 0,
MAG_FILTER_BILINEAR = 1,
MAG_FILTER_NONE = 2,
MAG_FILTER_BICUBIC = 3,
MAG_FILTER_SHARPEN = 4,
MAG_FILTER_ADD_DETAIL = 5,
MAG_FILTER_MODULATE_DETAIL = 6,
MAG_FILTER_BILINEAR_GEQUAL = 7,
MAG_FILTER_BILINEAR_LEQUAL = 8,
MAG_FILTER_BICUBIC_GEQUAL = 9,
MAG_FILTER_BICUBIC_LEQUAL = 10
};
enum WrapMode {
WRAP_REPEAT = 0,
WRAP_CLAMP = 1
};
enum TexEnvMode {
TEXENV_MODULATE = 0,
TEXENV_BLEND = 1,
TEXENV_DECAL = 2,
TEXENV_COLOR = 3
};
enum Projection {
PROJECTION_FLAT = 0,
PROJECTION_LAMBERT_CONIC = 3,
PROJECTION_UTM = 4,
PROJECTION_UNDEFINED = 7
};
enum Datum {
DATUM_WGS84 = 0,
DATUM_WGS72 = 1,
DATUM_BESSEL = 2,
DATUM_CLARK_1866 = 3,
DATUM_NAD27 = 4
};
Attr(int version) : _flt_version(version) { init(); }
void init();
void readField(ifstream& file, void* buf, size_t size);
bool readAttrFile(const char* szName);
StateSet* createOsgStateSet();
int32 texels_u; // Number of texels in u direction
int32 textel_v; // Number of texels in v direction
int32 direction_u; // Real world size u direction
int32 direction_v; // Real world size v direction
int32 x_up; // x component of up vector
int32 y_up; // y component of up vector
int32 fileFormat; // File format type
// -1 Not used
// 0 AT&T image 8 pattern
// 1 AT&T image 8 template
// 2 SGI intensity modulation
// 3 SGI intensity w/ alpha
// 4 SGI RGB
// 5 SGI RGB w/ alpha
int32 minFilterMode; // Minification filter type
// 0 - TX_POINT
// 1 - TX_BILINEAR
// 2 - TX_MIPMAP (Obsolete)
// 3 - TX_MIPMAP_POINT
// 4 - TX_MIPMAP_LINEAR
// 5 - TX_MIPMAP_BILINEAR
// 6 - TX_MIPMAP_TRILINEAR
// 7 - None
// 8 - TX_BICUBIC
// 9 - TX_BILINEAR_GEQUAL
// 10 - TX_BILINEAR_LEQUAL
// 11 - TX_BICUBIC_GEQUAL
// 12 - TX_BICUBIC_LEQUAL
int32 magFilterMode; // Magnification filter type
// 0 - TX_POINT
// 1 - TX_BILINEAR
// 2 - None
// 3 - TX_BICUBIC
// 4 - TX_SHARPEN
// 5 - TX_ADD_DETAIL
// 6 - TX_MODULATE_DETAIL
// 7 - TX_BILINEAR_GEQUAL
// 8 - TX_BILINEAR_LEQUAL
// 9 - TX_BICUBIC_GEQUAL
// 10 - TX_BICUBIC_LEQUAL
int32 wrapMode; // Repetition type
// 0 - TX_REPEAT
// 1 - TX_CLAMP
// 2 - (Obsolete)
int32 wrapMode_u; // Repetition type in u direction (see above)
int32 wrapMode_v; // Repetition type in v direction (see above)
int32 modifyFlag; // Modify flag (for internal use)
int32 pivot_x; // x pivot point for rotating textures
int32 pivot_y; // y pivot point for rotating textures
// --------------
// v11 ends here
// --------------
int32 texEnvMode; // Environment type
// 0 - TV_MODULATE
// 1 - TV_BLEND
// 2 - TV_DECAL
// 3 - TV_COLOR
int32 intensityAsAlpha; // TRUE if intensity pattern to be loaded in alpha with white in color
int32 spare1[8]; // 8 words of spare
float64 size_u; // Real world size u for floating point databases
float64 size_v; // Real world size v for floating point databases
int32 originCode; // Code for origin of imported texture
int32 kernelVersion; // Kernel version number
int32 intFormat; // Internal format type
// 0 - Default
// 1 - TX_I_12A_4
// 2 - TX_IA_8
// 3 - TX_RGB_5
// 4 - TX_RGBA_4
// 5 - TX_IA_12
// 6 - TX_RGBA_8
// 7 - TX_RGBA_12
// 8 - TX_I_16 (shadow mode only)
// 9 - TX_RGB_12
int32 extFormat; // External format type
// 0 - Default
// 1 - TX_PACK_8
// 2 - TX_PACK_16
int32 useMips; // TRUE if using following 8 floats for MIPMAP kernel
float32 mips[8]; // 8 floats for kernel of separable symmetric filter
int32 useLodScale; // Boolean if TRUE send:
float32 lod0; // LOD0 for TX_CONTROL_POINT
float32 scale0; // SCALE0 for TX_CONTROL_POINT
float32 lod1; // LOD1 for TX_CONTROL_POINT
float32 scale1; // SCALE1 for TX_CONTROL_POINT
float32 lod2; // LOD2 for TX_CONTROL_POINT
float32 scale2; // SCALE2 for TX_CONTROL_POINT
float32 lod3; // LOD3 for TX_CONTROL_POINT
float32 scale3; // SCALE3 for TX_CONTROL_POINT
float32 lod4; // LOD4 for TX_CONTROL_POINT
float32 scale4; // SCALE4 for TX_CONTROL_POINT
float32 lod5; // LOD5 for TX_CONTROL_POINT
float32 scale5; // SCALE5 for TX_CONTROL_POINT
float32 lod6; // LOD6 for TX_CONTROL_POINT
float32 scale6; // SCALE6 for TX_CONTROL_POINT
float32 lod7; // LOD7 for TX_CONTROL_POINT
float32 scale7; // SCALE7 for TX_CONTROL_POINT
float32 clamp; // Clamp
int32 magFilterAlpha; // magfilteralpha:
// 0 = TX_POINT
// 1 = TX_BILINEAR
// 2 = None
// 3 = TX_BICUBIC
// 4 = TX_SHARPEN
// 5 = TX_ADD_DETAIL
// 6 = TX_MODULATE_DETAIL
// 7 = TX_BILINEAR_GEQUAL
// 8 = TX_BILINEAR_LEQUAL
// 9 = TX_BICUBIC_GEQUAL
// 10 = TX_BIBICUBIC_LEQUAL
int32 magFilterColor; // magfiltercolor:
// 0 = TX_POINT
// 1 = TX_BILINEAR
// 2 = None
// 3 = TX_BICUBIC
// 4 = TX_SHARPEN
// 5 = TX_ADD_DETAIL
// 6 = TX_MODULATE_DETAIL
// 7 = TX_BILINEAR_GEQUAL
// 8 = TX_BILINEAR_LEQUAL
// 9 = TX_BICUBIC_GEQUAL
// 10 = TX_BIBICUBIC_LEQUAL
float32 reserved1; // Reserved
float32 reserved2[8]; // Reserved
float64 lambertMeridian; // Lambert conic projection central meridian
float64 lambertUpperLat; // Lambert conic projection upper latitude
float64 lambertlowerLat; // Lambert conic projection lower latitude
float64 reserved3; // Reserved
float32 spare2[5]; // Spare
int32 useDetail; // TRUE if using next 5 integers for detail texture
int32 txDetail_j; // J argument for TX_DETAIL
int32 txDetail_k; // K argument for TX_DETAIL
int32 txDetail_m; // M argument for TX_DETAIL
int32 txDetail_n; // N argument for TX_DETAIL
int32 txDetail_s; // Scramble argument for TX_DETAIL
int32 useTile; // TRUE if using next for floats for TX_TILE
float32 txTile_ll_u; // Lower-left u value for TX_TILE
float32 txTile_ll_v; // Lower-left v value for TX_TILE
float32 txTile_ur_u; // Upper-right u value for TX_TILE
float32 txTile_ur_v; // Upper-right v value for TX_TILE
int32 projection; // Projection
// 0 = Flat earth
// 3 = Lambert conic
// 4 = UTM
// 7 = Undefined projection
int32 earthModel; // Earth model
// 0 = WGS84
// 1 = WGS72
// 2 = Bessel
// 3 = Clark 1866
// 4 = NAD27
int32 reserved4; // Reserved
int32 utmZone; // UTM zone
int32 imageOrigin; // Image origin
// 0 = Lower-left
// 1 = Upper-left
int32 geoUnits; // Geospecific points units
// 0 = Degrees
// 1 = Meters
// 2 = Pixels
int32 reserved5; // Reserved
int32 reserved6; // Reserved
int32 hemisphere; // Hemisphere for geospecific points units
// 0 = Southern
// 1 = Northern
int32 reserved7; // Reserved
int32 reserved8; // Reserved
int32 spare3[149]; // Spare
char comments[512]; // Comments
// --------------
// v12 ends here
// --------------
int32 reserved9[13]; // Reserved
int32 attrVersion; // Attribute file version number
int32 controlPoints; // Number of geospecific control points
// If the number of geospecific control points is > 0,
// the following fields are also in the attribute file:
int32 reserved10; // Reserved
#if 0
// For each geospecific control point:
{
float64 texel_u; // Texel u of geospecific control point
float64 texel_v; // Texel v of geospecific control point
float64 geoPoint[2]; // Real earth coordinate of geospecific control point
// (this value depends on the projection, earth model,
// and geospecific points units)
}
// ----------------
// v15.6 ends here
// ----------------
// After all geospecific control points are listed, the following subtexture
// information appears:
int32 subtextures; // Number of subtexture definitions contained in the
// texture attribute file
// If the number of subtexture definitions is >0,
// the following fields are repeated for each subtexture definition:
{
char name[32]; // name of subtexture definition
int32 left; // Coordinate of left edge of subtexture
// definition measured in texels.
int32 bottom; // Coordinate of bottom edge of subtexture
// definition measured in texels.
int32 right; // Coordinate of right edge of subtexture
// definition measured in texels.
int32 top; // Coordinate of top edge of subtexture
// definition measured in texels.
}
#endif
void read();
private :
int _flt_version;
};
void Attr::init()
{
texels_u = 0;
textel_v = 0;
direction_u = 0;
direction_v = 0;
x_up = 0;
y_up = 0;
fileFormat = -1; // -1 Not used
minFilterMode = MIN_FILTER_NONE;
magFilterMode = MAG_FILTER_POINT;
wrapMode = WRAP_REPEAT;
wrapMode_u = WRAP_REPEAT;
wrapMode_v = WRAP_REPEAT;
modifyFlag = 0;
pivot_x = 0;
pivot_y = 0;
texEnvMode = TEXENV_MODULATE;
intensityAsAlpha = 0;
size_u = 0;
size_v = 0;
originCode = 0;
kernelVersion = 0;
intFormat = 0; // 0 - Default
extFormat = 0; // 0 - Default
useMips = 0;
// float32 mips[8];
useLodScale = 0;
// float32 lod0;
// float32 scale0;
// ...
// float32 lod7;
// float32 scale7;
clamp = 0;
magFilterAlpha = 2; // 2 = None
magFilterColor = 2; // 2 = None
lambertMeridian = 0;
lambertUpperLat = 0;
lambertlowerLat = 0;
useDetail = 0;
txDetail_j = 0;
txDetail_k = 0;
txDetail_m = 0;
txDetail_n = 0;
txDetail_s = 0;
useTile = 0;
txTile_ll_u = 0;
txTile_ll_v = 0;
txTile_ur_u = 0;
txTile_ur_v = 0;
projection = PROJECTION_UNDEFINED;
earthModel = DATUM_WGS84;
utmZone = 0;
imageOrigin = 0;
geoUnits = 0;
hemisphere = 1;
comments[0] = '\0';
attrVersion = 0;
controlPoints = 0;
// TODO:
}
void Attr::readField(ifstream& file, void* buf, size_t size)
{
if (file.eof()) return;
file.read((char*)buf, size);
if(::isLittleEndianMachine())
::endian2(buf, size, buf);
}
bool Attr::readAttrFile(const char* szName)
{
int n;
ifstream file;
file.open (szName, ios::in | ios::binary);
READ( texels_u );
READ( textel_v );
READ( direction_u );
READ( direction_v );
READ( x_up );
READ( y_up );
READ( fileFormat );
READ( minFilterMode );
READ( magFilterMode );
READ( wrapMode );
READ( wrapMode_u );
READ( wrapMode_v );
READ( modifyFlag );
READ( pivot_x );
READ( pivot_y );
// v11 ends here
if (_flt_version <= 11) return true;
READ( texEnvMode );
READ( intensityAsAlpha );
for (n=0; n<8; n++) {
READ(spare1[n]); }
READ( size_u );
READ( size_v );
READ( originCode );
READ( kernelVersion );
READ( intFormat );
READ( extFormat );
READ( useMips );
for (n=0; n<8; n++) {
READ(mips[n]); }
READ( useLodScale );
READ( lod0 );
READ( scale0 );
READ( lod1 );
READ( scale1 );
READ( lod2 );
READ( scale2 );
READ( lod3 );
READ( scale3 );
READ( lod4 );
READ( scale4 );
READ( lod5 );
READ( scale5 );
READ( lod6 );
READ( scale6 );
READ( lod7 );
READ( scale7 );
READ( clamp );
READ( magFilterAlpha );
READ( magFilterColor );
READ( reserved1 );
for (n=0; n<8; n++) {
READ(reserved2[n]); }
READ( lambertMeridian );
READ( lambertUpperLat );
READ( lambertlowerLat );
READ( reserved3 );
for (n=0; n<5; n++) {
READ(spare2[n]); }
READ( useDetail );
READ( txDetail_j );
READ( txDetail_k );
READ( txDetail_m );
READ( txDetail_n );
READ( txDetail_s );
READ( useTile );
READ( txTile_ll_u );
READ( txTile_ll_v );
READ( txTile_ur_u );
READ( txTile_ur_v );
READ( projection );
READ( earthModel );
READ( reserved4 );
READ( utmZone );
READ( imageOrigin);
READ( geoUnits );
READ( reserved5 );
READ( reserved6 );
READ( hemisphere );
READ( reserved7 );
READ( reserved8 );
for (n=0; n<149; n++) {
READ(spare3[n]); }
file.read(comments, sizeof(comments));
// v12 ends here
if (_flt_version <= 12) return true;
for (n=0; n<13; n++) {
READ(reserved9[n]); }
READ( attrVersion );
READ( controlPoints);
READ( reserved10 );
file.close();
return true;
}
StateSet* Attr::createOsgStateSet()
{
StateSet* osgStateSet = new StateSet;
TexEnv* osgTexEnv = new TexEnv;
Texture* osgTexture = new Texture;
if ((wrapMode_u != WRAP_CLAMP) && ((wrapMode_u != WRAP_REPEAT)))
wrapMode_u = wrapMode;
if ((wrapMode_v != WRAP_CLAMP) && ((wrapMode_v != WRAP_REPEAT)))
wrapMode_v = wrapMode;
if (wrapMode_u == WRAP_CLAMP) osgTexture->setWrap(Texture::WRAP_S,Texture::CLAMP);
else osgTexture->setWrap(Texture::WRAP_S,Texture::REPEAT);
if (wrapMode_v == WRAP_CLAMP) osgTexture->setWrap(Texture::WRAP_T,Texture::CLAMP);
else osgTexture->setWrap(Texture::WRAP_T,Texture::REPEAT);
switch (texEnvMode)
{
case TEXENV_MODULATE:
osgTexEnv->setMode(TexEnv::MODULATE);
break;
case TEXENV_BLEND:
osgTexEnv->setMode(TexEnv::BLEND);
break;
case TEXENV_DECAL:
osgTexEnv->setMode(TexEnv::DECAL);
break;
case TEXENV_COLOR:
osgTexEnv->setMode(TexEnv::REPLACE);
break;
}
// -----------
// Min filter
// -----------
switch (minFilterMode)
{
case MIN_FILTER_MIPMAP_POINT:
osgTexture->setFilter(osg::Texture::MIN_FILTER, Texture::LINEAR_MIPMAP_NEAREST);
break;
case MIN_FILTER_MIPMAP_LINEAR:
case MIN_FILTER_MIPMAP_BILINEAR:
case MIN_FILTER_MIPMAP_TRILINEAR:
osgTexture->setFilter(osg::Texture::MIN_FILTER, Texture::NEAREST_MIPMAP_LINEAR);
break;
// case MIN_FILTER_POINT:
// case MIN_FILTER_BILINEAR:
// case MIN_FILTER_BICUBIC;
// case MIN_FILTER_BILINEAR_GEQUAL:
// case MIN_FILTER_BILINEAR_LEQUAL:
// case MIN_FILTER_BICUBIC_GEQUAL:
// case MIN_FILTER_BICUBIC_LEQUAL:
// osgTexture->setFilter(osg::Texture::MIN_FILTER, Texture::LINEAR_MIPMAP_LINEAR);
// break;
}
// -----------
// Mag filter
// -----------
switch (magFilterMode)
{
case MAG_FILTER_POINT:
osgTexture->setFilter(osg::Texture::MAG_FILTER, Texture::NEAREST);
break;
case MAG_FILTER_BILINEAR:
case MAG_FILTER_BILINEAR_GEQUAL:
case MAG_FILTER_BILINEAR_LEQUAL:
case MAG_FILTER_SHARPEN:
osgTexture->setFilter(osg::Texture::MAG_FILTER, Texture::LINEAR);
break;
case MAG_FILTER_BICUBIC:
case MAG_FILTER_BICUBIC_GEQUAL:
case MAG_FILTER_BICUBIC_LEQUAL:
osgTexture->setFilter(osg::Texture::MAG_FILTER, Texture::ANISOTROPIC);
break;
// case MAG_FILTER_ADD_DETAIL:
// case MAG_FILTER_MODULATE_DETAIL:
// osgTexture->setFilter(osg::Texture::MAG_FILTER, Texture::ANISOTROPIC);
// break;
}
osgStateSet->setAttribute( osgTexEnv );
osgStateSet->setAttributeAndModes( osgTexture, StateAttribute::ON );
return osgStateSet;
}
class ReaderWriterATTR : public osgDB::ReaderWriter
{
public:
virtual const char* className() { return "ATTR Image Attribute Reader/Writer"; }
virtual bool acceptsExtension(const std::string& extension)
{
return osgDB::equalCaseInsensitive(extension,"attr");
}
virtual ReadResult readObject(const std::string& fileName, const osgDB::ReaderWriter::Options*)
{
std::string ext = osgDB::getFileExtension(fileName);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
// options
char buf[256];
int version=0;
const ReaderWriter::Options* rwOptions=
osgDB::Registry::instance()->getOptions();
if (rwOptions)
{
sscanf(rwOptions->getOptionString().c_str(),"%s %d", buf, &version);
if (strcmp(buf, "FLT_VER")) version=0;
}
Attr attr(version);
if (!attr.readAttrFile(fileName.c_str()))
{
return "Unable to open \""+fileName+"\"";
}
StateSet* stateset = attr.createOsgStateSet();
notify(INFO) << "texture attribute read ok" << endl;
return stateset;
}
};
// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterATTR> g_readerWriter_ATTR_Proxy;

View File

@@ -34,6 +34,7 @@ Record::Record()
{
_pData = NULL;
_pParent = NULL;
_pFltFile = NULL;
}
@@ -43,6 +44,15 @@ Record::~Record()
}
int Record::getFlightVersion()
{
if (_pFltFile)
return _pFltFile->getFlightVersion();
return -1;
}
Record* Record::cloneRecord(SRecHeader* pData)
{
Record* pRec = clone();
@@ -92,7 +102,7 @@ PrimNodeRecord::PrimNodeRecord()
// virtual
PrimNodeRecord::~PrimNodeRecord()
{
removeAllChildren();
// removeAllChildren();
}
@@ -152,7 +162,7 @@ bool PrimNodeRecord::readExtensionLevel(Input& fr)
{
Record* pRec;
while (pRec=fr.readCreateRecord())
while (pRec=fr.readCreateRecord(_pFltFile))
{
if (pRec->isOfType(POP_EXTENSION_OP))
return true;
@@ -192,12 +202,12 @@ bool PrimNodeRecord::readLevel(Input& fr)
// Read next record, including extension record
Record* PrimNodeRecord::readRecord(Input& fr)
{
Record* pRec = fr.readCreateRecord();
Record* pRec = fr.readCreateRecord(_pFltFile);
while (pRec && (pRec->getOpcode() == PUSH_EXTENSION_OP))
{
readExtensionLevel(fr);
pRec=fr.readCreateRecord();
pRec=fr.readCreateRecord(_pFltFile);
}
return pRec;
}

View File

@@ -19,8 +19,9 @@ using namespace std;
namespace flt {
class Record;
//class Record;
class Input;
class FltFile;
class RecordVisitor;
class FltFile;
class PrimNodeRecord;
@@ -53,7 +54,7 @@ class Record : public osg::Referenced
virtual bool isPrimaryNode() const { return false; }
virtual bool isControlRecord() const { return false; }
virtual bool isAncillaryRecord() const { return false; }
virtual void endian(){}
virtual void endian() {}
int getRecordType() const;
@@ -65,6 +66,9 @@ class Record : public osg::Referenced
size_t getBodyLength() const;
bool isOfType(int op) const;
Record* getParent() const { return _pParent; }
FltFile* getFltFile() { return _pFltFile; }
int getFlightVersion();
friend ostream& operator << (ostream& output, const Record& rec);
@@ -73,14 +77,15 @@ class Record : public osg::Referenced
/** disallow creation of Records on the stack.*/
virtual ~Record();
/** Template Method local read and write methods */
virtual bool readLocalData(Input& /*fr*/) { return false; }
// virtual bool writeLocalData(Output& fw) { return false; }
SRecHeader* _pData;
Record* _pParent;
FltFile* _pFltFile;
friend Input;
friend FltFile;
friend PrimNodeRecord;

View File

@@ -54,14 +54,14 @@ Record* Registry::getPrototype(const int opcode)
///////////////////////////////////////////////////////////////////
void Registry::addTexture(const std::string& name, osg::Texture* texture)
void Registry::addTexture(const std::string& name, osg::StateSet* texture)
{
if (texture == NULL) return;
_textureMap[name] = texture;
}
osg::Texture* Registry::getTexture(const std::string name)
osg::StateSet* Registry::getTexture(const std::string name)
{
TextureMap::iterator itr = _textureMap.find(name);
if (itr != _textureMap.end())

View File

@@ -7,7 +7,7 @@
#include <osg/Referenced>
#include <osg/ref_ptr>
#include <osg/Texture>
#include <osg/StateSet>
#include "FltFile.h"
@@ -47,19 +47,16 @@ class Registry
void addPrototype(Record* rec);
Record* getPrototype(const int opcode);
void addTexture(const std::string& name, osg::Texture* texture);
osg::Texture* getTexture(const std::string name);
void addTexture(const std::string& name, osg::StateSet* texture);
osg::StateSet* getTexture(const std::string name);
void addFltFile(const std::string& name, FltFile* file);
FltFile* getFltFile(const std::string& name);
inline void setVersion(int ver) { _fltFileVersion = ver; }
inline int getVersion() const { return _fltFileVersion; }
private:
typedef std::map<int, osg::ref_ptr<Record> > RecordProtoMap;
typedef std::map<std::string, osg::ref_ptr<osg::Texture> > TextureMap;
typedef std::map<std::string, osg::ref_ptr<osg::StateSet> > TextureMap;
typedef std::map<std::string, osg::ref_ptr<FltFile> > FltFileMap;
/** constructor is private, as its a singleton, preventing
@@ -70,8 +67,6 @@ class Registry
RecordProtoMap _recordProtoMap;
TextureMap _textureMap;
FltFileMap _fltFileMap;
int _fltFileVersion;
};

View File

@@ -29,10 +29,12 @@ struct STextureMapping
int32 diWarpFlag; // Warped flag; if TRUE, 8 point warp applied
float64 dfMat[4][4]; // Transformation matrix (valid only for Types 1 & 2)
// Variable Variable; // Parameters (see below for parameters for each mapping type)
};
#if 0
// Parameters for Put Texture Mapping (Type 1)
struct SPutTextureMapping
{
uint32 dwState; // State of Put Texture tool
// 0 = Start state - no points entered
// 1 = One point entered
@@ -49,17 +51,19 @@ struct STextureMapping
float64x3 dfTxtAlignment; // Texture alignment point
float64x3 dfTxtShear; // Texture shear point
float64x3 dfGeoOrigin; // Geometry origin point
float64x3 dfGeoAlignmentM // Geometry alignment point
float64x3 dfGeoAlignment; // Geometry alignment point
float64x3 dfGeoShear; // Geometry shear point
int32 TxtActive; // Active texture point
// 1 = Origin point
// 2 = Alignment point
// 3 = Shear point
int32 Reserved; // should always be set to 1
// Variable Variable; // Parameters (see parameters below for each mapping type)
};
//Parameters for 4 Point Put Texture Mapping (Type 2)
struct SPointPutTextureMapping
{
int32 state; // State of Put Texture tool
// 0 = Start state - no points entered
// 1 = One point entered
@@ -91,20 +95,25 @@ struct STextureMapping
int32 Reserved; // should always be set to 1
float32 sfScale; // Depth scale factor
float64 dfMat[4][4]; // Transformation matrix for the 4 point projection plane
};
// Parameters for Spherical Project Mapping (Type 4)
struct SSphericalTextureMapping
{
float32 sfScale; // Scale
float64x3 Center; // Center of the projection sphere
float32 sfScale; // Scale / (maximum dimension of the mapped geometry
float32 sfMaxScale; // Scale / (maximum dimension of the mapped geometry
// bounding box)
float32 sfMaxDimension; // Maximum dimension of the mapped geometry
// bounding box
};
// Parameters for Radial Project Mapping (Type 5)
int32 active // Active geometry point
struct SRadialTextureMapping
{
int32 active; // Active geometry point
// 1 = End point 1 of cylinder center line
// 2 = End point 2 of cylinder center line
int32 reserved; // Reserved
@@ -113,8 +122,11 @@ struct STextureMapping
float64 dfMat[4][4]; // Trackplane to XY plane transformation matrix
float64x3 endpoint1; // End point 1 of cylinder center line
float64x3 endpoint2; // End point 2 of cylinder center line
};
// Parameters for Warped Mapping (Warped Flag Set)
struct SWarpedTextureMapping
{
int32 active; // Active geometry point
// 0 = First warp FROM point
// 1 = Second warp FROM point
@@ -161,10 +173,10 @@ struct STextureMapping
Double 16*2 x, y of the seventh TO point transformed to the XY plane by the above matrix
Double 16*2 x, y of the eighth TO point transformed to the XY plane by the above matrix
*/
#endif
};
class TextureMappingPaletteRecord : public AncillaryRecord
{
public:

View File

@@ -12,14 +12,25 @@
namespace flt {
typedef struct TexturePaletteTag
struct STexturePalette
{
SRecHeader RecHeader;
char szFilename[200]; // Filename of texture pattern
char szFilename[200]; // Filename of texture pattern
int32 diIndex; // Pattern index
int32 diX; // x location in texture palette
int32 diY; // y location in texture palette
} STexturePalette;
};
// Version 10, 12, 13
struct SOldTexturePalette
{
SRecHeader RecHeader;
char szFilename[80]; // Filename of texture pattern
int32 diIndex; // Pattern index
int32 diX; // x location in texture palette
int32 diY; // y location in texture palette
};
class TexturePaletteRecord : public AncillaryRecord

View File

@@ -63,20 +63,20 @@ class VertexPaletteRecord : public AncillaryRecord
//
////////////////////////////////////////////////////////////////////
typedef struct VertexTag // Vertex with Color Record Format
struct SVertex // Vertex with Color Record Format
{
SRecHeader RecHeader;
uint16 swColor; // Color Name Index
uint16 swFlags; // Flags (bits, from left to right)
SRecHeader RecHeader;
uint16 swColor; // Color Name Index
uint16 swFlags; // Flags (bits, from left to right)
// 0 = Start Hard Edge
// 1 = Normal frozen
// 2 = no Vertex Color
// 3 = Packed Color
// 4-15 Spare
float64x3 Coord; // x,y,z coordinate
float64x3 Coord; // x,y,z coordinate
color32 PackedColor; // Packed color (A, B, G, R)
uint32 dwVertexColorIndex;
} SVertex;
uint32 dwVertexColorIndex;
};
class VertexRecord : public AncillaryRecord
@@ -106,21 +106,21 @@ class VertexRecord : public AncillaryRecord
////////////////////////////////////////////////////////////////////
typedef struct NormalVertexTag // Vertex with Normal Record Format
struct SNormalVertex // Vertex with Normal Record Format
{
SRecHeader RecHeader;
uint16 swColor; // Color Name Index
uint16 swFlags; // Flags (bits, from left to right)
SRecHeader RecHeader;
uint16 swColor; // Color Name Index
uint16 swFlags; // Flags (bits, from left to right)
// 0 = Start Hard Edge
// 1 = Normal frozen
// 2 = no Vertex Color
// 3 = Packed Color
// 4-15 Spare
float64x3 Coord; // x,y,z coordinate
float32x3 Normal; // Vertex normal
float64x3 Coord; // x,y,z coordinate
float32x3 Normal; // Vertex normal
color32 PackedColor; // Packed color (A, B, G, R)
uint32 dwVertexColorIndex;
} SNormalVertex;
uint32 dwVertexColorIndex;
};
class NormalVertexRecord : public AncillaryRecord
@@ -149,21 +149,21 @@ class NormalVertexRecord : public AncillaryRecord
//
////////////////////////////////////////////////////////////////////
typedef struct TextureVertexTag // Vertex with Texture Record Format
struct STextureVertex // Vertex with Texture Record Format
{
SRecHeader RecHeader;
uint16 swColor; // Color Name Index
uint16 swFlags; // Flags (bits, from left to right)
SRecHeader RecHeader;
uint16 swColor; // Color Name Index
uint16 swFlags; // Flags (bits, from left to right)
// 0 = Start Hard Edge
// 1 = Normal frozen
// 2 = no Vertex Color
// 3 = Packed Color
// 4-15 Spare
float64x3 Coord; // x,y,z coordinate
float32x2 Texture; // Texture (u,v)
float64x3 Coord; // x,y,z coordinate
float32x2 Texture; // Texture (u,v)
color32 PackedColor; // Packed color (A, B, G, R)
uint32 dwVertexColorIndex;
} STextureVertex;
};
class TextureVertexRecord : public AncillaryRecord
@@ -192,22 +192,22 @@ class TextureVertexRecord : public AncillaryRecord
//
////////////////////////////////////////////////////////////////////
typedef struct NormalTextureVertexTag //Vertex with Normal and Texture Format
struct SNormalTextureVertex //Vertex with Normal and Texture Format
{
SRecHeader RecHeader;
uint16 swColor; // Color Name Index
uint16 swFlags; // Flags (bits, from left to right)
SRecHeader RecHeader;
uint16 swColor; // Color Name Index
uint16 swFlags; // Flags (bits, from left to right)
// 0 = Start Hard Edge
// 1 = Normal frozen
// 2 = no Vertex Color
// 3 = Packed Color
// 4-15 Spare
float64x3 Coord; // x,y,z coordinate
float32x3 Normal; // Vertex normal
float32x3 Normal; // Vertex normal
float32x2 Texture; // Texture (u,v)
color32 PackedColor; // Packed color (A, B, G, R)
uint32 dwVertexColorIndex;
} SNormalTextureVertex;
color32 PackedColor; // Packed color (A, B, G, R)
uint32 dwVertexColorIndex;
};
class NormalTextureVertexRecord : public AncillaryRecord

View File

@@ -41,3 +41,4 @@ void flt::endian2(void* pSrc, int nSrc, void* pDst, int )
*(1 + (long *)pDst) = tmp1;
}
}

View File

@@ -33,6 +33,24 @@ namespace flt {
#define BIT14 0x4000
#define BIT15 0x8000
#define BIT16 0x00010000
#define BIT17 0x00020000
#define BIT18 0x00040000
#define BIT19 0x00080000
#define BIT20 0x00100000
#define BIT21 0x00200000
#define BIT22 0x00400000
#define BIT23 0x00800000
#define BIT24 0x01000000
#define BIT25 0x02000000
#define BIT26 0x04000000
#define BIT27 0x08000000
#define BIT28 0x10000000
#define BIT29 0x20000000
#define BIT30 0x40000000
#define BIT31 0x80000000
////////////////////////////////////////////////////////////////////
typedef signed char int8;

View File

@@ -1,7 +1,8 @@
// flt2osg.cpp
#include <stdio.h>
#include <string.h>
#include "osg/GL"
#include <osg/GL>
#include <osg/Group>
#include <osg/LOD>
@@ -12,6 +13,9 @@
#include <osg/StateSet>
#include <osg/CullFace>
#include <osg/TexEnv>
#include <osg/TexGen>
#include <osg/AlphaFunc>
#include <osg/Transparency>
#include <osg/Point>
#include <osg/Material>
#include <osg/PolygonOffset>
@@ -39,6 +43,7 @@
#include "OldMaterialPaletteRecord.h"
#include "TexturePaletteRecord.h"
#include "VertexPoolRecords.h"
#include "OldVertexRecords.h"
#include "GroupRecord.h"
#include "LodRecord.h"
#include "DofRecord.h"
@@ -52,16 +57,19 @@
#include "GeoSetBuilder.h"
#include "LongIDRecord.h"
using namespace flt;
ConvertFromFLT::ConvertFromFLT(FltFile* pFltFile)
ConvertFromFLT::ConvertFromFLT() :
_faceColor(1,1,1,1)
{
_pFltFile = pFltFile;
_diOpenFlightVersion = 0;
_diCurrentOffset = 0;
_wObjTransparency = 0;
_nSubfaceLevel = 0;
_sfHdrUnitScale = 1;
_unitScale = 1.0;
_bHdrRgbMode = false;
}
@@ -71,7 +79,7 @@ ConvertFromFLT::~ConvertFromFLT()
}
osg::Node* ConvertFromFLT::convert(Record* rec)
osg::Node* ConvertFromFLT::convert(HeaderRecord* rec)
{
if (rec==NULL) return NULL;
return visitNode(NULL, rec);
@@ -150,7 +158,8 @@ osg::Node* ConvertFromFLT::visitAncillary(osg::Group* osgParent, PrimNodeRecord*
osg::Node* ConvertFromFLT::visitPrimaryNode(osg::Group* osgParent, PrimNodeRecord* rec)
{
osg::Node* node = NULL;
GeoSetBuilder geoSetBuilder(_pFltFile.get());
osg::Geode* geode = new osg::Geode;
GeoSetBuilder geoSetBuilder(geode);
// Visit
for(int i=0; i < rec->getNumChildren(); i++)
@@ -168,8 +177,9 @@ osg::Node* ConvertFromFLT::visitPrimaryNode(osg::Group* osgParent, PrimNodeRecor
}
}
osg::Geode* geode = geoSetBuilder.createOsgGeoSets();
if (osgParent && geode)
geoSetBuilder.createOsgGeoSets();
if (osgParent && (geode->getNumDrawables() > 0))
osgParent->addChild( geode );
return node;
@@ -195,10 +205,35 @@ osg::Node* ConvertFromFLT::visitHeader(osg::Group* osgParent, HeaderRecord* rec)
osg::notify(osg::INFO) << "Version " << _diOpenFlightVersion << endl;
// Unit scale
if (pSHeader->iMultDivUnit < 0)
_sfHdrUnitScale = 1.f / -pSHeader->iMultDivUnit;
else if (pSHeader->iMultDivUnit > 0)
_sfHdrUnitScale = pSHeader->iMultDivUnit;
switch (pSHeader->swVertexCoordUnit)
{
case HeaderRecord::METERS:
_unitScale = 1.0;
break;
case HeaderRecord::KILOMETERS:
_unitScale = 1000.0;
break;
case HeaderRecord::FEET:
_unitScale = 0.3048;
break;
case HeaderRecord::INCHES:
_unitScale = 0.02540;
break;
case HeaderRecord::NAUTICAL_MILES:
_unitScale = 1852.0;
break;
default:
_unitScale = 1.0;
}
// Flight v.11 & v.12 use integer coordinates
if (rec->getFlightVersion() < 13)
{
if (pSHeader->iMultDivUnit >= 0)
_unitScale *= (double)pSHeader->iMultDivUnit;
else
_unitScale /= (double)(-pSHeader->iMultDivUnit);
}
_bHdrRgbMode = (pSHeader->dwFlags & 0x40000000) ? true : false; // RGB space (=packed color)
@@ -220,14 +255,17 @@ osg::Node* ConvertFromFLT::visitHeader(osg::Group* osgParent, HeaderRecord* rec)
/*osgParent*/
osg::Node* ConvertFromFLT::visitColorPalette(osg::Group* , ColorPaletteRecord* rec)
{
if (!_pFltFile->useColorPalette()) return NULL;
if (!rec->getFltFile()->useInternalColorPalette()) return NULL;
ColorPool* pColorPool = _pFltFile->getColorPool();
ColorPool* pColorPool = rec->getFltFile()->getColorPool();
int flightVersion = rec->getFlightVersion();
if (_diOpenFlightVersion > 13)
if (flightVersion > 13)
{
SColorPalette* pCol = (SColorPalette*)rec->getData();
for (int i=0; i < 1024; i++)
int colors = (flightVersion >= 1500) ? 1024 : 512;
for (int i=0; i < colors; i++)
{
osg::Vec4 color(pCol->Colors[i].get());
color[3] = 1.0f; // Force alpha to one
@@ -256,14 +294,13 @@ osg::Node* ConvertFromFLT::visitColorPalette(osg::Group* , ColorPaletteRecord* r
return NULL;
}
/*osgParent*/
osg::Node* ConvertFromFLT::visitMaterialPalette(osg::Group* , MaterialPaletteRecord* rec)
osg::Node* ConvertFromFLT::visitMaterialPalette(osg::Group*, MaterialPaletteRecord* rec)
{
if (!_pFltFile->useMaterialPalette()) return NULL;
if (!rec->getFltFile()->useInternalMaterialPalette()) return NULL;
SMaterial* pSMaterial = (SMaterial*)rec->getData();
MaterialPool* pMaterialPool = _pFltFile->getMaterialPool();
MaterialPool* pMaterialPool = rec->getFltFile()->getMaterialPool();
if (pSMaterial && pMaterialPool)
{
MaterialPool::PoolMaterial* pPoolMat = new MaterialPool::PoolMaterial;
@@ -283,10 +320,10 @@ osg::Node* ConvertFromFLT::visitMaterialPalette(osg::Group* , MaterialPaletteRec
/*osgParent*/
osg::Node* ConvertFromFLT::visitOldMaterialPalette(osg::Group* , OldMaterialPaletteRecord* rec)
{
if (!_pFltFile->useMaterialPalette()) return NULL;
if (!rec->getFltFile()->useInternalMaterialPalette()) return NULL;
SOldMaterial* pSMaterial = (SOldMaterial*)rec->getData();
MaterialPool* pMaterialPool = _pFltFile->getMaterialPool();
MaterialPool* pMaterialPool = rec->getFltFile()->getMaterialPool();
if (pSMaterial && pMaterialPool )
{
@@ -310,37 +347,85 @@ osg::Node* ConvertFromFLT::visitOldMaterialPalette(osg::Group* , OldMaterialPale
/*osgParent*/
osg::Node* ConvertFromFLT::visitTexturePalette(osg::Group* , TexturePaletteRecord* rec)
{
if (!_pFltFile->useTexturePalette()) return NULL;
int nIndex;
char* pFilename;
STexturePalette* pTexture = (STexturePalette*)rec->getData();
TexturePool* pTexturePool = _pFltFile->getTexturePool();
if (!rec->getFltFile()->useInternalTexturePalette()) return NULL;
if (pTexture && pTexturePool)
if (rec->getFlightVersion() > 13)
{
osg::Texture *osgTexture;
STexturePalette* pTexture = (STexturePalette*)rec->getData();
pFilename = pTexture->szFilename;
nIndex = pTexture->diIndex;
}
else // version 11, 12 & 13
{
SOldTexturePalette* pOldTexture = (SOldTexturePalette*)rec->getData();
pFilename = pOldTexture->szFilename;
nIndex = pOldTexture->diIndex;
}
osgTexture = Registry::instance()->getTexture(pTexture->szFilename);
if (osgTexture == NULL)
TexturePool* pTexturePool = rec->getFltFile()->getTexturePool();
if (pTexturePool == NULL) return NULL;
// Get StateSet containing texture from registry pool.
osg::StateSet *osgStateSet = Registry::instance()->getTexture(pFilename);
if (osgStateSet)
{
// Add texture to local pool to be able to get by index.
pTexturePool->addTexture(nIndex, osgStateSet);
return NULL;
}
// Read texture and texture
osg::ref_ptr<osg::Image> image = osgDB::readImageFile(pFilename);
if (image.valid())
{
std::string attrName(pFilename);
attrName += ".attr";
// Read attribute file
char options[256];
sprintf(options,"FLT_VER %d",rec->getFlightVersion());
osgDB::Registry::instance()->setOptions(new osgDB::ReaderWriter::Options(options));
osg::StateSet* osgStateSet =
dynamic_cast<osg::StateSet*>(osgDB::readObjectFile(attrName));
osgDB::Registry::instance()->setOptions(NULL); // Delete options
// if not found create default StateSet
if (osgStateSet == NULL)
{
osg::ref_ptr<osg::Image> image = osgDB::readImageFile(pTexture->szFilename);
if (image.valid())
{
osgTexture = new osg::Texture;
osgTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::REPEAT );
osgTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT );
osgTexture->setImage(image.get());
// set up trilinear filtering.
osgTexture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR_MIPMAP_LINEAR);
osgTexture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
// Add new texture to registry
Registry::instance()->addTexture(pTexture->szFilename, osgTexture);
}
osgStateSet = new osg::StateSet;
osg::TexEnv* osgTexEnv = new osg::TexEnv;
osgTexEnv->setMode(osg::TexEnv::MODULATE);
osgStateSet->setAttribute( osgTexEnv );
}
if (osgTexture)
pTexturePool->addTexture((int)pTexture->diIndex, osgTexture);
osg::Texture *osgTexture = dynamic_cast<osg::Texture*>(osgStateSet->getAttribute( osg::StateAttribute::TEXTURE));
if (osgTexture == NULL)
{
osgTexture = new osg::Texture;
osgStateSet->setAttributeAndModes(osgTexture,osg::StateAttribute::ON);
}
osgTexture->setImage(image.get());
switch (image->pixelFormat())
{
case GL_LUMINANCE_ALPHA:
case GL_RGBA:
osgStateSet->setMode(GL_BLEND,osg::StateAttribute::ON);
osgStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
break;
}
// Add new texture to registry pool
Registry::instance()->addTexture(pFilename, osgStateSet);
// Also add to local pool to be able to get texture by index.
pTexturePool->addTexture(nIndex, osgStateSet);
}
return NULL;
@@ -353,7 +438,6 @@ osg::Node* ConvertFromFLT::visitVertexPalette(osg::Group* , VertexPaletteRecord*
return NULL;
}
/*osgParent*/
osg::Node* ConvertFromFLT::visitVertex(osg::Group* , VertexRecord* rec)
{
@@ -362,7 +446,6 @@ osg::Node* ConvertFromFLT::visitVertex(osg::Group* , VertexRecord* rec)
return NULL;
}
/*osgParent*/
osg::Node* ConvertFromFLT::visitNormalVertex(osg::Group* , NormalVertexRecord* rec)
{
@@ -371,7 +454,6 @@ osg::Node* ConvertFromFLT::visitNormalVertex(osg::Group* , NormalVertexRecord* r
return NULL;
}
/*osgParent*/
osg::Node* ConvertFromFLT::visitTextureVertex(osg::Group* , TextureVertexRecord* rec)
{
@@ -380,7 +462,6 @@ osg::Node* ConvertFromFLT::visitTextureVertex(osg::Group* , TextureVertexRecord*
return NULL;
}
/*osgParent*/
osg::Node* ConvertFromFLT::visitNormalTextureVertex(osg::Group* , NormalTextureVertexRecord* rec)
{
@@ -512,6 +593,7 @@ osg::Node* ConvertFromFLT::visitSwitch(osg::Group* osgParent, SwitchRecord* rec)
osg::Node* ConvertFromFLT::visitObject(osg::Group* osgParent, ObjectRecord* rec)
{
SObject *pSObject = (SObject*)rec->getData();
osg::Group* group = new osg::Group;
if (group)
@@ -520,11 +602,11 @@ osg::Node* ConvertFromFLT::visitObject(osg::Group* osgParent, ObjectRecord* rec)
if (node) osgParent = (osg::Group*)node;
unsigned short wPrevTransparency = _wObjTransparency;
_wObjTransparency = rec->getData()->wTransparency;
_wObjTransparency = pSObject->wTransparency;
visitPrimaryNode(group, (PrimNodeRecord*)rec);
_wObjTransparency = wPrevTransparency;
group->setName(rec->getData()->szIdent);
group->setName(pSObject->szIdent);
osgParent->addChild( group );
}
@@ -534,12 +616,21 @@ osg::Node* ConvertFromFLT::visitObject(osg::Group* osgParent, ObjectRecord* rec)
void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
{
osg::GeoSet* geoSet = pBuilder->getGeoSet();
osg::StateSet* stateSet = geoSet->getStateSet();
DynGeoSet* dgset = pBuilder->getDynGeoSet();
osg::StateSet* osgStateSet = dgset->getStateSet();
SFace *pSFace = (SFace*)rec->getData();
osg::Vec4 color(1,1,1,1);
if (rec->getFlightVersion() > 13)
{
if (pSFace->dwFlags & FaceRecord::HIDDEN_BIT)
return;
}
//
// Cull face & wireframe
//
int drawMode = pSFace->swDrawFlag & (BIT0 | BIT1);
switch(drawMode)
{
@@ -548,21 +639,21 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
{
osg::CullFace* cullface = new osg::CullFace;
cullface->setMode(osg::CullFace::BACK);
stateSet->setAttributeAndModes(cullface, osg::StateAttribute::ON);
osgStateSet->setAttributeAndModes(cullface, osg::StateAttribute::ON);
}
break;
case FaceRecord::SOLID_NO_BACKFACE:
// Disable backface culling
stateSet->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
osgStateSet->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
break;
case FaceRecord::WIREFRAME_NOT_CLOSED:
geoSet->setPrimType(osg::GeoSet::LINE_STRIP);
dgset->setPrimType(osg::GeoSet::LINE_STRIP);
break;
case FaceRecord::WIREFRAME_CLOSED:
geoSet->setPrimType(osg::GeoSet::LINE_LOOP);
dgset->setPrimType(osg::GeoSet::LINE_LOOP);
break;
}
/*
@@ -581,66 +672,84 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
*/
//
// Lighting and color binding
if (_diOpenFlightVersion > 13)
//
if (rec->getFlightVersion() > 13)
{
switch(pSFace->swLightMode)
{
case FaceRecord::FACE_COLOR:
// Use face color, not illuminated
stateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
geoSet->setColorBinding( osg::GeoSet::BIND_OVERALL );
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
dgset->setColorBinding( osg::GeoSet::BIND_OVERALL /*BIND_PERPRIM*/ );
break;
case FaceRecord::VERTEX_COLOR:
// Use vertex colors, not illuminated
stateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
geoSet->setColorBinding( osg::GeoSet::BIND_PERVERTEX );
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
dgset->setColorBinding( osg::GeoSet::BIND_PERVERTEX );
break;
case FaceRecord::FACE_COLOR_LIGHTING:
// Use face color and vertex normal
stateSet->setMode( GL_LIGHTING, osg::StateAttribute::ON );
geoSet->setColorBinding( osg::GeoSet::BIND_OVERALL );
geoSet->setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::ON );
dgset->setColorBinding( osg::GeoSet::BIND_OVERALL );
dgset->setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
break;
case FaceRecord::VERTEX_COLOR_LIGHTING:
// Use vertex color and vertex normal
stateSet->setMode( GL_LIGHTING, osg::StateAttribute::ON );
geoSet->setColorBinding( osg::GeoSet::BIND_PERVERTEX );
geoSet->setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::ON );
dgset->setColorBinding( osg::GeoSet::BIND_PERVERTEX );
dgset->setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
break;
default :
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
dgset->setColorBinding( osg::GeoSet::BIND_OVERALL );
break;
}
}
else // Version 11, 12 & 13
{
geoSet->setColorBinding( osg::GeoSet::BIND_OVERALL );
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
dgset->setColorBinding( osg::GeoSet::BIND_OVERALL /*BIND_PERPRIM*/ );
}
//
// Face Color
//
if (pSFace->swTexWhite && (pSFace->iTexturePattern != -1))
{
// Render textured polygons white
_faceColor.set(1,1,1,1);
}
else
{
float alpha = 1.0f;
ColorPool* pColorPool = _pFltFile->getColorPool();
ColorPool* pColorPool = rec->getFltFile()->getColorPool();
_faceColor.set(1,1,1,1);
if (_diOpenFlightVersion > 13)
if (rec->getFlightVersion() > 13)
{
if (!(pSFace->dwFlags & FaceRecord::NO_COLOR_BIT))
{
float alpha;
bool bPackedColor =
_bHdrRgbMode ||
(pSFace->dwFlags & FaceRecord::PACKED_COLOR_BIT) ||
(pColorPool == NULL);
if (bPackedColor)
color = pSFace->PrimaryPackedColor.get();
_faceColor = pSFace->PrimaryPackedColor.get();
else
color = pColorPool->getColor(pSFace->dwPrimaryColorIndex);
_faceColor = pColorPool->getColor(pSFace->dwPrimaryColorIndex);
alpha = 1.0f - (float)pSFace->wTransparency / 65535.0f;
color[3] = alpha;
_faceColor[3] = alpha;
}
}
else // Version 11, 12 & 13
@@ -648,27 +757,32 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
bool bPackedColor = _bHdrRgbMode || (pColorPool == NULL);
if (bPackedColor)
color = pSFace->PrimaryPackedColor.get();
_faceColor = pSFace->PrimaryPackedColor.get();
else
color = pColorPool->getColor(pSFace->wPrimaryNameIndex);
_faceColor = pColorPool->getColor(pSFace->wPrimaryNameIndex);
alpha = 1.0f - (float)pSFace->wTransparency / 65535.0f;
color[3] = alpha;
_faceColor[3] = alpha;
}
// Transparency
if (alpha < 1.0f)
{
stateSet->setMode(GL_BLEND,osg::StateAttribute::ON);
stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
osgStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
osgStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}
if (geoSet->getColorBinding() == osg::GeoSet::BIND_OVERALL)
geoSet->setColors( new osg::Vec4(color) );
}
if ((dgset->getColorBinding() == osg::GeoSet::BIND_OVERALL)
|| (dgset->getColorBinding() == osg::GeoSet::BIND_PERPRIM))
dgset->addColor(_faceColor);
//
// Material
MaterialPool* pMaterialPool = _pFltFile->getMaterialPool();
//
MaterialPool* pMaterialPool = rec->getFltFile()->getMaterialPool();
if (pMaterialPool)
{
MaterialPool::PoolMaterial* pSMaterial = pMaterialPool->getMaterial((int)pSFace->iMaterial);
@@ -685,14 +799,14 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
alpha = pSMaterial->sfAlpha * (1.0f - (
((float)pSFace->wTransparency / 65535.0f) * ((float)_wObjTransparency / 65535.0f) ));
ambient[0] = pSMaterial->Ambient[0] * color[0];
ambient[1] = pSMaterial->Ambient[1] * color[1];
ambient[2] = pSMaterial->Ambient[2] * color[2];
ambient[0] = pSMaterial->Ambient[0] * _faceColor[0];
ambient[1] = pSMaterial->Ambient[1] * _faceColor[1];
ambient[2] = pSMaterial->Ambient[2] * _faceColor[2];
ambient[3] = alpha;
diffuse[0] = pSMaterial->Diffuse[0] * color[0];
diffuse[1] = pSMaterial->Diffuse[1] * color[1];
diffuse[2] = pSMaterial->Diffuse[2] * color[2];
diffuse[0] = pSMaterial->Diffuse[0] * _faceColor[0];
diffuse[1] = pSMaterial->Diffuse[1] * _faceColor[1];
diffuse[2] = pSMaterial->Diffuse[2] * _faceColor[2];
diffuse[3] = alpha;
specular[0] = pSMaterial->Specular[0];
@@ -705,7 +819,6 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
emissiv[2] = pSMaterial->Emissive[2];
emissiv[3] = alpha;
// osgMaterial->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
osgMaterial->setAmbient(osg::Material::FRONT_AND_BACK, ambient);
osgMaterial->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
osgMaterial->setSpecular(osg::Material::FRONT_AND_BACK, specular);
@@ -715,15 +828,18 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
if (alpha < 1.0f)
{
stateSet->setMode(GL_BLEND,osg::StateAttribute::ON);
stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
osgStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
osgStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}
stateSet->setAttribute(osgMaterial);
osgStateSet->setAttribute(osgMaterial);
}
}
//
// Subface
//
if (rec->getParent()->isOfType(FACE_OP))
{
if (_nSubfaceLevel > 0)
@@ -733,102 +849,66 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
{
polyoffset->setFactor(-1.0f*_nSubfaceLevel);
polyoffset->setUnits(-20.0f*_nSubfaceLevel);
stateSet->setAttributeAndModes(polyoffset,osg::StateAttribute::ON);
osgStateSet->setAttributeAndModes(polyoffset,osg::StateAttribute::ON);
}
}
}
//
// Texture
//
if (pSFace->iTexturePattern != -1)
{
TexturePool* pTexturePool = _pFltFile->getTexturePool();
TexturePool* pTexturePool = rec->getFltFile()->getTexturePool();
if (pTexturePool)
{
osg::Texture* osgTexture = pTexturePool->getTexture((int)pSFace->iTexturePattern);
if (osgTexture)
osg::StateSet *textureStateSet = dynamic_cast<osg::StateSet *>
(pTexturePool->getTexture((int)pSFace->iTexturePattern));
if (textureStateSet)
{
osg::Image* image = osgTexture->getImage();
if (image)
// Merge face stateset with texture stateset
osgStateSet->merge(*textureStateSet);
// current version of merge dosn't merge rendering hint
if (textureStateSet->getRenderingHint() == osg::StateSet::TRANSPARENT_BIN)
osgStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
#if 0 // Started to experiment with OpenFlight texture mapping modes
if (pSFace->iTextureMapIndex > -1)
{
switch (image->pixelFormat())
{
case GL_LUMINANCE_ALPHA:
case GL_RGBA:
stateSet->setMode(GL_BLEND,osg::StateAttribute::ON);
stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
break;
}
osg::TexGen* osgTexGen = new osg::TexGen;
osgTexGen->setMode(osg::TexGen::SPHERE_MAP);
osgStateSet->setAttributeAndModes(osgTexGen,osg::StateAttribute::ON);
}
#endif
geoSet->setTextureBinding(osg::GeoSet::BIND_PERVERTEX);
// TODO: Crrect when .attr loader implemented
osg::TexEnv* osgTexEnv = new osg::TexEnv;
osgTexEnv->setMode(osg::TexEnv::MODULATE);
stateSet->setAttribute( osgTexEnv );
stateSet->setAttributeAndModes( osgTexture, osg::StateAttribute::ON );
dgset->setTextureBinding(osg::GeoSet::BIND_PERVERTEX);
}
}
}
// Visit vertices
if (_diOpenFlightVersion > 13)
{
int i;
for(i=0; i < rec->getNumChildren(); i++)
{
Record* child = rec->getChild(i);
if (child == NULL) break;
//
// Vertices
//
switch (child->getOpcode())
{
case VERTEX_LIST_OP:
pBuilder->addPrimLen(
visitVertexList(pBuilder, (VertexListRecord*)child));
break;
}
}
}
else
{
int i;
int vertices=0;
for(i=0; i < rec->getNumChildren(); i++)
{
Record* child = rec->getChild(i);
if (child == NULL) break;
addVertices(pBuilder, rec);
switch (child->getOpcode())
{
case OLD_VERTEX_OP:
pBuilder->addVertex(child);
vertices++;
break;
//
// Add face to builder GeoSet pool
//
case OLD_VERTEX_COLOR_OP:
geoSet->setColorBinding( osg::GeoSet::BIND_PERVERTEX );
pBuilder->addVertex(child);
vertices++;
break;
case OLD_VERTEX_COLOR_NORMAL_OP:
geoSet->setColorBinding( osg::GeoSet::BIND_PERVERTEX );
pBuilder->addVertex(child);
vertices++;
break;
}
}
pBuilder->addPrimLen(vertices);
}
// Add primitives to GeoSet and prepare for next.
pBuilder->addPrimitive();
//
// Look for subfaces
{
int n;
//
{
_nSubfaceLevel++;
int n;
for(n=0; n<rec->getNumChildren(); n++)
{
Record* child = rec->getChild(n);
@@ -841,9 +921,38 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
}
// Return number of vertices added to builder.
int ConvertFromFLT::addVertices(GeoSetBuilder* pBuilder, PrimNodeRecord* primRec)
{
int i;
int vertices=0;
DynGeoSet* dgset = pBuilder->getDynGeoSet();
for(i=0; i < primRec->getNumChildren(); i++)
{
Record* child = primRec->getChild(i);
if (child == NULL) break;
switch (child->getOpcode())
{
case VERTEX_LIST_OP:
vertices += visitVertexList(pBuilder, (VertexListRecord*)child);
break;
default :
vertices += addVertex(pBuilder, child);
break;
}
}
if (vertices > 0) dgset->addPrimLen(vertices);
return vertices;
}
int ConvertFromFLT::visitVertexList(GeoSetBuilder* pBuilder, VertexListRecord* rec)
{
osg::GeoSet* geoSet = pBuilder->getGeoSet();
DynGeoSet* dgset = pBuilder->getDynGeoSet();
int vertices = rec->numberOfVertices();
// Add vertices to GeoSetBuilder
@@ -851,12 +960,130 @@ int ConvertFromFLT::visitVertexList(GeoSetBuilder* pBuilder, VertexListRecord* r
{
Record* vertex = getVertexFromPool(rec->getVertexPoolOffset(i));
if (vertex)
pBuilder->addVertex(vertex);
addVertex(pBuilder, vertex);
}
return vertices;
}
// Return 1 if record is a known vertex record else return 0.
int ConvertFromFLT::addVertex(GeoSetBuilder* pBuilder, Record* rec)
{
DynGeoSet* dgset = pBuilder->getDynGeoSet();
switch(rec->getOpcode())
{
case VERTEX_C_OP:
{
SVertex* pVert = (SVertex*)rec->getData();
osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z());
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
}
break;
case VERTEX_CN_OP:
{
SNormalVertex* pVert = (SNormalVertex*)rec->getData();
osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z());
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX)
ADD_NORMAL(dgset, pVert)
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
}
break;
case VERTEX_CNT_OP:
{
SNormalTextureVertex* pVert = (SNormalTextureVertex*)rec->getData();
osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z());
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX)
ADD_NORMAL(dgset, pVert)
if (dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
ADD_TCOORD(dgset, pVert)
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
}
break;
case VERTEX_CT_OP:
{
STextureVertex* pVert = (STextureVertex*)rec->getData();
osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z());
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
ADD_TCOORD(dgset, pVert)
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
}
break;
case OLD_VERTEX_OP:
{
SOldVertex* pVert = (SOldVertex*)rec->getData();
osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]);
coord *= (float)_unitScale;
dgset->addCoord(coord);
if ((dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
&& (rec->getSize() >= sizeof(SOldVertex)))
ADD_OLD_TCOORD(dgset, pVert)
}
break;
case OLD_VERTEX_COLOR_OP:
{
SOldVertexColor* pVert = (SOldVertexColor*)rec->getData();
osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]);
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
ADD_OLD_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
if ((dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
&& (rec->getSize() >= sizeof(SOldVertexColor)))
ADD_OLD_TCOORD(dgset, pVert)
}
break;
case OLD_VERTEX_COLOR_NORMAL_OP:
{
SOldVertexColorNormal* pVert = (SOldVertexColorNormal*)rec->getData();
osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]);
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX)
{
osg::Vec3 normal(pVert->n[0], pVert->n[1], pVert->n[2]);
normal /= (float)(1L<<30);
dgset->addNormal(normal);
}
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
ADD_OLD_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
if ((dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
&& (rec->getSize() >= sizeof(SOldVertexColorNormal)))
ADD_OLD_TCOORD(dgset, pVert)
}
break;
default :
return 0;
}
return 1;
}
osg::Node* ConvertFromFLT::visitMatrix(osg::Group* osgParent, MatrixRecord* rec)
{
SMatrix* pSMatrix = (SMatrix*)rec->getData();
@@ -872,6 +1099,14 @@ osg::Node* ConvertFromFLT::visitMatrix(osg::Group* osgParent, MatrixRecord* rec)
m(i,j) = pSMatrix->sfMat[i][j];
}
}
// scale position.
// BJ Don't know if this should be done if version > 12
osg::Vec3 pos = m.getTrans();
m *= osg::Matrix::trans(-pos.x(),-pos.y(),-pos.z());
pos *= (float)_unitScale;
m *= osg::Matrix::trans(pos);
dcs->setMatrix(m);
osgParent->addChild(dcs);
return (osg::Node*)dcs;
@@ -907,51 +1142,27 @@ osg::Node* ConvertFromFLT::visitExternal(osg::Group* osgParent, ExternalRecord*
void ConvertFromFLT::visitLightPoint(GeoSetBuilder* pBuilder, LightPointRecord* rec)
{
osg::GeoSet* geoSet = pBuilder->getGeoSet();
osg::StateSet* stateSet = geoSet->getStateSet();
DynGeoSet* dgset = pBuilder->getDynGeoSet();
osg::StateSet* stateSet = dgset->getStateSet();
SLightPoint *pSLightPoint = (SLightPoint*)rec->getData();
geoSet->setPrimType(osg::GeoSet::POINTS);
geoSet->setColorBinding(osg::GeoSet::BIND_PERVERTEX);
dgset->setPrimType(osg::GeoSet::POINTS);
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateSet->setMode(GL_POINT_SMOOTH, osg::StateAttribute::ON);
dgset->setColorBinding(osg::GeoSet::BIND_PERVERTEX);
osg::Point* point = new osg::Point;
if (point)
{
point->setSize( pSLightPoint->sfSize );
point->setSize(pSLightPoint->sfSize);
stateSet->setAttributeAndModes( point, osg::StateAttribute::ON );
// point->setFadeThresholdSize(const float fadeThresholdSize);
// point->setDistanceAttenuation(const Vec3& distanceAttenuation);
// point->setStateSetModes(*stateSet,const GLModeValue value); // GL_POINT_SMOOTH
// point->setStateSetModes(*stateSet, osg::StateAttribute::ON); // GL_POINT_SMOOTH
}
// Visit vertices
for(int i=0; i < rec->getNumChildren(); i++)
{
Record* child = rec->getChild(i);
if (child)
{
int op = child->getOpcode();
switch (op)
{
case VERTEX_LIST_OP:
{
int vertices = visitVertexList(pBuilder, (VertexListRecord*)child);
for (int v=0; v<vertices; v++)
pBuilder->addPrimLen(1);
}
break;
case OLD_VERTEX_OP:
case OLD_VERTEX_COLOR_OP:
case OLD_VERTEX_COLOR_NORMAL_OP:
pBuilder->addVertex(child);
pBuilder->addPrimLen(1);
break;
}
}
}
addVertices(pBuilder, rec);
pBuilder->addPrimitive();
}

View File

@@ -6,13 +6,12 @@
#include <osg/ref_ptr>
#include <osg/Vec4>
#include "Record.h"
#include "FltFile.h"
#include <map>
#include <vector>
#include <string>
#include "Record.h"
#include "GeoSetBuilder.h"
namespace osg {
class Object;
@@ -52,19 +51,62 @@ class LightPointRecord;
class VertexListRecord;
class LongIDRecord;
class GeoSetBuilder;
//class GeoSetBuilder;
struct SMaterial;
#define ADD_NORMAL(DGSET,VERTEX) \
(DGSET)->addNormal(osg::Vec3( \
(float)(VERTEX)->Normal.x(), \
(float)(VERTEX)->Normal.y(), \
(float)(VERTEX)->Normal.z()));
#define ADD_VERTEX_COLOR(DGSET,VERTEX,COLOR_POOL) \
{ \
if ((VERTEX)->swFlags & V_NO_COLOR_BIT) \
(DGSET)->addColor(_faceColor); \
else \
{ \
if ((VERTEX)->swFlags & V_PACKED_COLOR_BIT) \
(DGSET)->addColor(pVert->PackedColor.get()); \
else \
(DGSET)->addColor((COLOR_POOL)->getColor((VERTEX)->dwVertexColorIndex)); \
} \
}
#define ADD_TCOORD(DGSET,VERTEX) \
(DGSET)->addTCoord(osg::Vec2( \
(float)(VERTEX)->Texture.x(), \
(float)(VERTEX)->Texture.y()));
#define ADD_OLD_COLOR(DGSET,VERTEX,COLOR_POOL) \
{ \
if (COLOR_POOL) \
(DGSET)->addColor((COLOR_POOL)->getColor((VERTEX)->color_index)); \
else \
(DGSET)->addColor(osg::Vec4(1,1,1,1)); \
}
#define ADD_OLD_TCOORD(DGSET,VERTEX) \
(DGSET)->addTCoord(osg::Vec2( \
(float)(VERTEX)->t[0], \
(float)(VERTEX)->t[1]));
#define ADD_OLD_NORMAL(DGSET,VERTEX) \
(DGSET)->addNormal(osg::Vec3( \
(float)pVert->n[0] / (1<<30), \
(float)pVert->n[1] / (1<<30), \
(float)pVert->n[2] / (1<<30)));
class ConvertFromFLT
{
public:
ConvertFromFLT(FltFile* pFltFile);
ConvertFromFLT();
virtual ~ConvertFromFLT();
osg::Node* convert(Record* rec);
osg::Node* convert(HeaderRecord* rec);
osg::Node* visitNode(osg::Group* osgParent,Record* rec);
osg::Node* visitAncillary(osg::Group* osgParent, PrimNodeRecord* rec);
@@ -97,20 +139,21 @@ class ConvertFromFLT
private:
int addVertices(GeoSetBuilder* pBuilder, PrimNodeRecord* primRec);
int addVertex(GeoSetBuilder* pBuilder, Record* rec);
Record* getVertexFromPool(int nOffset);
void regisiterVertex(int nOffset, Record* pRec);
typedef std::map<int,Record*> VertexPaletteOffsetMap;
VertexPaletteOffsetMap _VertexPaletteOffsetMap;
osg::ref_ptr<FltFile> _pFltFile;
int _diOpenFlightVersion;
int _diCurrentOffset;
unsigned short _wObjTransparency;
int _nSubfaceLevel;
float _sfHdrUnitScale; // iMultDivUnit
double _unitScale;
bool _bHdrRgbMode;
osg::Vec4 _faceColor;
};

View File

@@ -8,43 +8,43 @@
#define UNKNOWN_OP 0
#define HEADER_OP 1
#define GROUP_OP 2
#define HEADER_OP 1
#define GROUP_OP 2
#define OLD_LOD_OP 3
#define OBJECT_OP 4
#define FACE_OP 5
#define OBJECT_OP 4
#define FACE_OP 5
#define OLD_VERTEX_OP 7
#define OLD_VERTEX_COLOR_OP 8
#define OLD_VERTEX_COLOR_NORMAL_OP 9
#define PUSH_LEVEL_OP 10
#define POP_LEVEL_OP 11
#define DOF_OP 14
#define PUSH_LEVEL_OP 10
#define POP_LEVEL_OP 11
#define DOF_OP 14
#define PUSH_SUBFACE_OP 19
#define POP_SUBFACE_OP 20
#define PUSH_EXTENSION_OP 21
#define POP_EXTENSION_OP 22
#define COMMENT_OP 31
#define COLOR_PALETTE_OP 32
#define COMMENT_OP 31
#define COLOR_PALETTE_OP 32
#define LONG_ID_OP 33
/*
Ignore 40-48
#define OLD_TRANSLATE_OP 44
*/
#define MATRIX_OP 49
#define MATRIX_OP 49
#define VECTOR_OP 50
#define REPLICATE_OP 60
#define INSTANCE_REFERENCE_OP 61
#define INSTANCE_DEFINITION_OP 62
#define EXTERNAL_REFERENCE_OP 63
#define TEXTURE_PALETTE_OP 64
#define REPLICATE_OP 60
#define INSTANCE_REFERENCE_OP 61
#define INSTANCE_DEFINITION_OP 62
#define EXTERNAL_REFERENCE_OP 63
#define TEXTURE_PALETTE_OP 64
#define OLD_MATERIAL_PALETTE_OP 66
#define VERTEX_PALETTE_OP 67
#define VERTEX_PALETTE_OP 67
#define VERTEX_C_OP 68
#define VERTEX_CN_OP 69
#define VERTEX_CNT_OP 70
#define VERTEX_CT_OP 71
#define VERTEX_LIST_OP 72
#define LOD_OP 73
#define LOD_OP 73
#define BOUNDING_BOX_OP 74
/*
Ignore 76-82