From Daniel Sjölie - added support for multitexured flt files.

This commit is contained in:
Robert Osfield 2002-09-18 11:11:10 +00:00
parent ed43d97ed3
commit 4a54b7bdb1
16 changed files with 472 additions and 16 deletions

View File

@ -123,6 +123,10 @@ Ruben Lopez <ryu@gpul.org>
Pavel Moloshtan <pasha@moloshtan.com>
- Support for LWO2 format in the LightWave loader.
Daniel Sjölie <deepone@acc.umu.se>
- Support for multitextured flt files.
Alberto Barbati <abarbati@iaanus.com>
- lazy evaluation of the inverse in the MatrixTransform.

View File

@ -120,7 +120,7 @@ SOURCE=..\..\..\src\osgPlugins\flt\ExtensionRecord.cpp
SOURCE=..\..\..\src\osgPlugins\flt\ExternalRecord.cpp
# End Source File
# Begin Source File
\
SOURCE=..\..\..\src\osgPlugins\flt\FaceRecord.cpp
# End Source File
# Begin Source File
@ -181,6 +181,10 @@ SOURCE=..\..\..\src\osgPlugins\flt\MeshRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\MultiTextureRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LodRecord.cpp
# End Source File
# Begin Source File
@ -249,6 +253,10 @@ SOURCE=..\..\..\src\osgPlugins\flt\TransformationRecords.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\UVListRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\UnknownRecord.cpp
# End Source File
# Begin Source File
@ -365,6 +373,10 @@ SOURCE=..\..\..\src\osgPlugins\flt\MaterialPaletteRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\MultiTextureRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ObjectRecord.h
# End Source File
# Begin Source File
@ -421,6 +433,10 @@ SOURCE=..\..\..\src\osgPlugins\flt\TransformationRecords.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\UVListRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\UnknownRecord.h
# End Source File
# Begin Source File

View File

@ -101,10 +101,6 @@ SOURCE=..\..\src\osgUtil\CullVisitor.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgUtil\DepthSortedBin.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgUtil\DisplayListVisitor.cpp
# End Source File
# Begin Source File
@ -189,10 +185,6 @@ SOURCE=..\..\Include\osgUtil\CullVisitor
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgUtil\DepthSortedBin
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgUtil\DisplayListVisitor
# End Source File
# Begin Source File

View File

@ -81,6 +81,7 @@ const osg::Primitive::Mode NO_PRIMITIVE_TYPE = (osg::Primitive::Mode)0xffff;
DynGeoSet::DynGeoSet()
{
_primtype=NO_PRIMITIVE_TYPE;
_geom = new osg::Geometry;
}
void DynGeoSet::setBinding()
@ -108,8 +109,6 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom)
{
int indexBase = 0;
geom->setStateSet(getStateSet());
osg::Vec3Array* vertices = geom->getVertexArray();
if (vertices)
{
@ -240,9 +239,13 @@ osg::Geode* GeoSetBuilder::createOsgGeoSets(osg::Geode* geode)
itr!=_dynGeoSetList.end();
++itr)
{
osg::Geometry* geom = new osg::Geometry;
DynGeoSet* dgset = itr->get();
osg::Geometry* geom = dgset->getGeometry();
geode->addDrawable(geom);
(*itr)->addToGeometry(geom);
dgset->addToGeometry(geom);
osg::StateSet* stateset = dgset->getStateSet();
assert( stateset == geom->getStateSet() );
}
osgUtil::Tesselator tesselator;

View File

@ -96,7 +96,10 @@ class DynGeoSet : public osg::Referenced
bool operator == (const DynGeoSet& rhs) const { return compare(rhs)==0; }
bool operator != (const DynGeoSet& rhs) const { return compare(rhs)!=0; }
void setStateSet(osg::StateSet* stateset) { _stateset = stateset; }
void setStateSet(osg::StateSet* stateset) {
_stateset = stateset;
_geom->setStateSet( stateset );
}
osg::StateSet* getStateSet() { return _stateset.get(); }
const osg::StateSet* getStateSet() const { return _stateset.get(); }
@ -128,6 +131,12 @@ class DynGeoSet : public osg::Referenced
inline const int colorListSize() const { return _colorList.size(); }
inline const int tcoordListSize() const { return _tcoordList.size(); }
osg::Geometry* getGeometry() {
CERR << "_geom.get(): " << _geom.get()
<< "; referenceCount: " << _geom.get()->referenceCount()<<"\n";
return _geom.get();
};
private:
typedef std::vector<int> PrimLenList;
@ -136,6 +145,7 @@ class DynGeoSet : public osg::Referenced
typedef std::vector<osg::Vec4> ColorList;
typedef std::vector<osg::Vec2> TcoordList;
osg::ref_ptr<osg::Geometry> _geom;
osg::ref_ptr<osg::StateSet> _stateset;

View File

@ -43,6 +43,8 @@ CXXFILES =\
TextureMappingPaletteRecord.cpp\
ReaderWriterFLT.cpp\
ReaderWriterATTR.cpp\
MultiTextureRecord.cpp\
UVListRecord.cpp\
# PointLight.cpp\

View File

@ -0,0 +1,38 @@
// MultiTextureRecord.cpp
#include "flt.h"
#include "Registry.h"
#include "MultiTextureRecord.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// MultiTextureRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<MultiTextureRecord> g_MultiTextureProxy;
MultiTextureRecord::MultiTextureRecord()
{
CERR << "MultiTextureRecord created\n";
}
// virtual
MultiTextureRecord::~MultiTextureRecord()
{
}
// virtual
void MultiTextureRecord::endian()
{
int flightVersion = getFlightVersion();
SMultiTexture *pSMultiTexture = (SMultiTexture*)getData();
ENDIAN( pSMultiTexture->layers );
}

View File

@ -0,0 +1,59 @@
// MultiTextureRecord.h
#ifndef __FLT_MULTI_TEXTURE_RECORD_H
#define __FLT_MULTI TEXTURE_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
struct STextureLayer {
uint16 texture;
uint16 effect;
uint16 mapping;
uint16 data;
void endian() {
ENDIAN( texture );
ENDIAN( effect );
ENDIAN( mapping );
ENDIAN( data );
};
};
struct SMultiTexture
{
SRecHeader RecHeader;
uint32 layers;
STextureLayer data[1];
};
class MultiTextureRecord : public AncillaryRecord
{
public:
MultiTextureRecord();
virtual Record* clone() const { return new MultiTextureRecord(); }
virtual const char* className() const { return "MultiTextureRecord"; }
virtual int classOpcode() const { return MULTI_TEXTURE_OP; }
virtual size_t sizeofData() const { return sizeof(SMultiTexture); }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
protected:
virtual ~MultiTextureRecord();
virtual void endian();
};
}; // end namespace flt
#endif

View File

@ -225,6 +225,8 @@ Record* PrimNodeRecord::readRecord(Input& fr)
return pRec;
}
#include "UVListRecord.h"
#include <stdio.h>
// virtual
bool PrimNodeRecord::readLocalData(Input& fr)
@ -237,6 +239,21 @@ bool PrimNodeRecord::readLocalData(Input& fr)
while (pRec && pRec->isAncillaryRecord())
{
addChild(pRec);
if ( pRec->getOpcode() == 52 ) {
CERR << "Multitexture added to " << this << "(opcode: "
<< getOpcode() << ")\n";
}
if ( pRec->getOpcode() == 53 ) {
CERR << "UV list added to " << this << "(opcode: "
<< getOpcode() << ")\n";
UVListRecord* mtr =
dynamic_cast<UVListRecord*>(pRec);
assert( mtr );
assert( mtr->isAncillaryRecord() );
SUVList* mt =
reinterpret_cast<SUVList*>(mtr->getData());
assert( mt );
}
pRec = readRecord(fr);
}

View File

@ -34,8 +34,11 @@ void Registry::addPrototype(Record* rec)
Record* Registry::getPrototype(const int opcode)
{
RecordProtoMap::iterator itr = _recordProtoMap.find(opcode);
if (itr != _recordProtoMap.end())
if (itr != _recordProtoMap.end()) {
return (*itr).second.get();
}
osg::notify( osg::WARN )
<< "flt::Registry::addPrototype: Unkown opcode: " << opcode << "\n";
return NULL;

View File

@ -0,0 +1,36 @@
// UVListRecord.cpp
#include "flt.h"
#include "Registry.h"
#include "UVListRecord.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// UVListRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<UVListRecord> g_UVListProxy;
UVListRecord::UVListRecord()
{
CERR << "UVListRecord created\n";
}
// virtual
UVListRecord::~UVListRecord()
{
}
// virtual
void UVListRecord::endian()
{
SUVList *pSUVList = (SUVList*)getData();
ENDIAN( pSUVList->layers );
}

View File

@ -0,0 +1,66 @@
// UVListRecord.h
#ifndef __FLT_UV_LIST_RECORD_H
#define __FLT_UV_LIST_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
struct SVertexUV {
float32x2 coords;
void endian() {
ENDIAN( coords );
};
};
struct SMorphUV {
float32x2 coords0;
float32x2 coords100;
void endian() {
ENDIAN( coords0 );
ENDIAN( coords100 );
};
};
struct SUVList
{
SRecHeader RecHeader;
uint32 layers;
union {
SVertexUV vertex[1];
SMorphUV morph[1];
} coords;
};
class UVListRecord : public AncillaryRecord
{
public:
UVListRecord();
virtual Record* clone() const { return new UVListRecord(); }
virtual const char* className() const { return "UVListRecord"; }
virtual int classOpcode() const { return UV_LIST_OP; }
virtual size_t sizeofData() const { return sizeof(SUVList); }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~UVListRecord();
virtual void endian();
};
}; // end namespace flt
#endif

View File

@ -15,6 +15,10 @@
#include <sys/types.h>
#endif
#include <osg/Notify>
#define CERR osg::notify( osg::INFO ) << __FILE__ << ":" << __LINE__ << ": "
#define CERR2 osg::notify( osg::NOTICE )<< __FILE__ << ":" << __LINE__ << ": "
namespace flt {
#define ENDIAN2(SRC, DST) endian2((void*)&(SRC), sizeof(SRC), (void*)&(DST), sizeof(DST))

View File

@ -60,6 +60,8 @@
#include "LongIDRecord.h"
#include "InstanceRecords.h"
#include "LocalVertexPoolRecord.h"
#include "MultiTextureRecord.h"
#include "UVListRecord.h"
@ -199,6 +201,9 @@ osg::Group* ConvertFromFLT::visitAncillary(osg::Group& osgParent, osg::Group& os
case VERTEX_CT_OP:
visitTextureVertex(osgPrimary, (TextureVertexRecord*)child);
break;
default:
osg::notify( osg::INFO ) << "flt::ConvertFromFLT::visitAncillary: "
<< "Unknown opcode: " << child->getOpcode() << "\n";
}
}
return parent;
@ -465,6 +470,7 @@ void ConvertFromFLT::visitTexturePalette(osg::Group& , TexturePaletteRecord* rec
if (!rec->getFltFile()->useInternalTexturePalette()) return;
if (rec->getFlightVersion() > 13)
{
STexturePalette* pTexture = (STexturePalette*)rec->getData();
@ -481,6 +487,7 @@ void ConvertFromFLT::visitTexturePalette(osg::Group& , TexturePaletteRecord* rec
TexturePool* pTexturePool = rec->getFltFile()->getTexturePool();
if (pTexturePool == NULL) return;
// Get StateSet containing texture from registry pool.
osg::StateSet *osgStateSet = Registry::instance()->getTexture(pFilename);
@ -491,6 +498,7 @@ void ConvertFromFLT::visitTexturePalette(osg::Group& , TexturePaletteRecord* rec
return; // Texture already loaded
}
CERR<<"visitTexturePalette attempting to load ("<<pFilename<<")"<<std::endl;
unsigned int unit = 0;
@ -541,6 +549,10 @@ void ConvertFromFLT::visitTexturePalette(osg::Group& , TexturePaletteRecord* rec
// Also add to local pool to be able to get texture by index.
// ( umm... should this have reference to the texture unit? RO. July2002)
pTexturePool->addTexture(nIndex, osgStateSet);
CERR<<"Registry::instance()->addTexture("<<pFilename<<", "<<osgStateSet<<")"<<std::endl;
CERR<<"pTexturePool->addTexture("<<nIndex<<", "<<osgStateSet<<")"<<std::endl;
}
}
@ -1209,6 +1221,107 @@ void ConvertFromFLT::setTransparency ( osg::StateSet *osgStateSet, bool &bBlend
}
}
void
ConvertFromFLT::addMultiTexture( DynGeoSet* dgset, MultiTextureRecord* mtr )
{
osg::Geometry* geom = dgset->getGeometry();
assert( geom );
assert( mtr );
assert( mtr->isAncillaryRecord() );
SMultiTexture* mt =
reinterpret_cast<SMultiTexture*>(mtr->getData());
assert( mt );
CERR << "ConvertFromFLT::addMultiTexture\n";
int l = 0;
for ( int i = 0; i < 8; i++ ) {
if ( (1 << 32-i) & mt->layers ) {
CERR << "Has layer " << i << "\n";
mt->data[l].endian();
CERR << "texture: " << mt->data[l].texture << "\n";
CERR << "effect: " << mt->data[l].effect << "\n";
CERR << "mapping: " << mt->data[l].mapping << "\n";
CERR << "data: " << mt->data[l].data << "\n";
TexturePool* pTexturePool = mtr->getFltFile()->getTexturePool();
assert( pTexturePool );
osg::StateSet *textureStateSet = dynamic_cast<osg::StateSet *>
(pTexturePool->getTexture((int)mt->data[l].texture));
CERR << "pTexturePool->getTexture((int)mt->data[l].texture): " << pTexturePool->getTexture((int)mt->data[l].texture) << "\n";
CERR << "textureStateSet: " << textureStateSet << "\n";
assert( textureStateSet );
osg::Texture2D *texture =
dynamic_cast<osg::Texture2D*>(
textureStateSet->getTextureAttribute(
0, osg::StateAttribute::TEXTURE));
CERR << "texture: " << texture << "\n";
osg::StateSet* texture_stateset = new osg::StateSet;
CERR << "texture_stateset: " << texture_stateset << "\n";
assert( texture );
texture_stateset->setTextureAttributeAndModes(
i, texture,osg::StateAttribute::ON);
osg::TexEnv* osgTexEnv = new osg::TexEnv;
CERR << "osgTexEnv: " << osgTexEnv << "\n";
osgTexEnv->setMode(osg::TexEnv::MODULATE);
texture_stateset->setTextureAttribute( i, osgTexEnv );
assert( geom );
CERR << "geom: " << geom << "\n";
CERR << ", referenceCount: "
<< geom->referenceCount() << "\n";
osg::StateSet* geom_stateset = geom->getStateSet();
CERR << "geom_stateset: " << geom_stateset << "\n";
if ( geom_stateset ) {
geom_stateset->merge( *texture_stateset );
CERR << "Merging layer " << i << "\n";
} else {
geom->setStateSet( texture_stateset );
CERR << "Setting layer " << i << "\n";
}
l++;
}
}
}
void
ConvertFromFLT::addUVList( DynGeoSet* dgset, UVListRecord* uvr )
{
osg::Geometry* geom = dgset->getGeometry();
assert( geom );
assert( uvr );
assert( uvr->isAncillaryRecord() );
SUVList* uvl =
reinterpret_cast<SUVList*>(uvr->getData());
assert( uvl );
CERR << "ConvertFromFLT::addUVList\n";
int l = 0;
int num_coords = dgset->coordListSize();
for ( int i = 0; i < 8; i++ ) {
if ( (1 << 32-i) & uvl->layers ) {
osg::Vec2Array* tcoords = new osg::Vec2Array;
CERR << "Has layer " << i << "\n";
// Assume we are working with vertex lists for now
for ( int v = l*num_coords; v < (l+1)*num_coords; v++ ) {
uvl->coords.vertex[v].endian();
CERR << "( u: " << uvl->coords.vertex[v].coords[1] << ", "
<< "v: " << uvl->coords.vertex[v].coords[0] << ")\n";
/// FIXME: should be (x,y) instead of (y,x) - ENDIAN problem???
tcoords->push_back( osg::Vec2( uvl->coords.vertex[v].coords[1],
uvl->coords.vertex[v].coords[0] ) );
}
if ( !tcoords->empty() ) {
CERR << "Setting tcoords " << i << ": " << tcoords << "\n";
geom->setTexCoordArray( i, tcoords );
}
l++;
}
}
}
void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
{
@ -1257,6 +1370,30 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
// Add face to builder pool
pBuilder->addPrimitive();
// Visit ancillary records
for(int i=0; i < rec->getNumChildren(); i++)
{
Record* child = rec->getChild(i);
if (!child->isAncillaryRecord())
break;
switch (child->getOpcode())
{
case MULTI_TEXTURE_OP:
{
MultiTextureRecord* mtr =
dynamic_cast<MultiTextureRecord*>(child);
assert( mtr );
addMultiTexture( dgset, mtr );
}
break;
default:
osg::notify( osg::WARN ) << "flt::ConvertFromFLT::visitFace: "
<< "Unhandled opcode: " << child->getOpcode() << "\n";
break;
}
}
// Look for subfaces
{
_nSubfaceLevel++;
@ -1320,7 +1457,7 @@ int ConvertFromFLT::addVertices(GeoSetBuilder* pBuilder, PrimNodeRecord* primRec
int ConvertFromFLT::visitVertexList(GeoSetBuilder* pBuilder, VertexListRecord* rec)
{
//DynGeoSet* dgset = pBuilder->getDynGeoSet();
DynGeoSet* dgset = pBuilder->getDynGeoSet();
int vertices = rec->numberOfVertices();
// Add vertices to GeoSetBuilder
@ -1331,6 +1468,41 @@ int ConvertFromFLT::visitVertexList(GeoSetBuilder* pBuilder, VertexListRecord* r
addVertex(pBuilder, vertex);
}
// Visit ancillary records
for(int i=0; i < rec->getNumChildren(); i++)
{
Record* child = rec->getChild(i);
CERR << "OPCODE: " << child->getOpcode() << "\n";
if (!child->isAncillaryRecord())
break;
switch (child->getOpcode())
{
case UV_LIST_OP:
{
UVListRecord* uvr =
dynamic_cast<UVListRecord*>(child);
assert( uvr );
addUVList( dgset, uvr );
}
break;
case MULTI_TEXTURE_OP:
{
CERR2 << "MULTI_TEXTURE_OP in visitVertexList\n";
MultiTextureRecord* mtr =
dynamic_cast<MultiTextureRecord*>(child);
assert( mtr );
addMultiTexture( dgset, mtr );
}
break;
default:
osg::notify( osg::WARN )
<< "flt::ConvertFromFLT::visitVertexList: "
<< "Unhandled opcode: " << child->getOpcode() << "\n";
break;
}
}
return vertices;
}
@ -1547,6 +1719,32 @@ void ConvertFromFLT::visitMesh ( osg::Group &parent, GeoSetBuilder *pBuilder, Me
// Add the mesh primitives.
addMeshPrimitives ( parent, pBuilder, rec );
// Visit ancillary records
for(int i=0; i < rec->getNumChildren(); i++)
{
Record* child = rec->getChild(i);
if (!child->isAncillaryRecord())
break;
switch (child->getOpcode())
{
case MULTI_TEXTURE_OP:
{
CERR2 << "MULTI_TEXTURE_OP in visitMesh\n";
MultiTextureRecord* mtr =
dynamic_cast<MultiTextureRecord*>(child);
assert( mtr );
addMultiTexture( dgset, mtr );
}
break;
default:
osg::notify( osg::WARN ) << "flt::ConvertFromFLT::visitFace: "
<< "Unhandled opcode: " << child->getOpcode() << "\n";
break;
}
}
}

View File

@ -52,6 +52,8 @@ class LocalVertexPoolRecord;
class LongIDRecord;
class InstanceDefinitionRecord;
class InstanceReferenceRecord;
class MultiTextureRecord;
class UVListRecord;
struct SFace;
//class GeoSetBuilder;
@ -170,6 +172,10 @@ class ConvertFromFLT
void setTexture ( FaceRecord *rec, SFace *pSFace, osg::StateSet *osgStateSet, DynGeoSet *dgset, bool &bBlend );
void setTransparency ( osg::StateSet *osgStateSet, bool &bBlend );
// multitexturing
void addMultiTexture( DynGeoSet* dgset, MultiTextureRecord* mtr );
void addUVList( DynGeoSet* dgset, UVListRecord* mtr );
typedef std::map<int,Record*> VertexPaletteOffsetMap;
VertexPaletteOffsetMap _VertexPaletteOffsetMap;

View File

@ -32,6 +32,8 @@ Ignore 40-48
*/
#define MATRIX_OP 49
#define VECTOR_OP 50
#define MULTI_TEXTURE_OP 52
#define UV_LIST_OP 53
#define REPLICATE_OP 60
#define INSTANCE_REFERENCE_OP 61
#define INSTANCE_DEFINITION_OP 62