From Brede Johansen,

"- Replaced some member attributes with local variables in Face record.
 - Multitexture support in Vertex class.
 - Renamed VertexList to VertexListRecord (VertexList is now a Vertex array)
 - new Mesh (with reserved field at offset 12, thanks to Paul Martz)
 - new LocalVertexPool
 - new MeshPrimitive
 - Use ProxyNode for externals.
 - Local cache for externals"
This commit is contained in:
Robert Osfield
2006-05-15 11:18:50 +00:00
parent e00bf394c8
commit 132b355d4f
8 changed files with 788 additions and 197 deletions

View File

@@ -19,7 +19,8 @@
namespace flt {
/* Face record
*/
class Face : public PrimaryRecord
{
// flags
@@ -32,31 +33,11 @@ class Face : public PrimaryRecord
static const unsigned int ROOFLINE_BIT = 0x80000000u >> 6;
osg::Vec4 _primaryColor;
int32 _IRColor;
int16 _relativePriority;
uint8 _drawFlag;
uint8 _texturedWhite;
int16 _primaryNameIndex;
int16 _secondaryNameIndex;
uint8 _template;
int _detailTexture;
int _textureIndex;
int _materialIndex;
int16 _surface;
int16 _feature;
int32 _IRMaterial;
uint16 _transparency;
uint8 _influenceLOD;
uint8 _linestyle;
uint32 _flags;
uint8 _lightMode;
osg::Vec4 _primaryPackedColor;
osg::Vec4 _secondaryPackedColor;
int _textureMappingIndex;
int _primaryColorIndex;
int _alternateColorIndex;
int _shaderIndex;
osg::ref_ptr<osg::Geode> _geode;
osg::ref_ptr<osg::Geometry> _geometry;
@@ -126,14 +107,11 @@ public:
inline bool isAlphaBlend() const
{
return (_template==FIXED_ALPHA_BLENDING) ||
(_template==AXIAL_ROTATE_WITH_ALPHA_BLENDING) ||
(_template==POINT_ROTATE_WITH_ALPHA_BLENDING);
(_template==AXIAL_ROTATE_WITH_ALPHA_BLENDING) ||
(_template==POINT_ROTATE_WITH_ALPHA_BLENDING);
}
virtual osg::Vec4 getPrimaryColor() const { return _primaryColor; }
inline int getMaterialIndex() const { return _materialIndex; }
inline int getTextureIndex() const { return _textureIndex; }
inline int getTextureMappingIndex() const { return _textureMappingIndex; }
inline osg::Vec4 getPrimaryColor() const { return _primaryColor; }
inline float getTransparency() const { return (float)_transparency / 65535.0f; }
inline bool isTransparent() const { return _transparency > 0; }
@@ -170,10 +148,13 @@ public:
normals->push_back(vertex._normal);
}
if (vertex.validUV())
for (int layer=0; layer<Vertex::MAX_LAYERS; layer++)
{
osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,0);
UVs->push_back(vertex._uv);
if (vertex.validUV(layer))
{
osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,layer);
UVs->push_back(vertex._uv[layer]);
}
}
}
@@ -209,10 +190,13 @@ public:
normals->push_back(vertex0._normal);
}
if (vertex0.validUV())
for (int layer=0; layer<Vertex::MAX_LAYERS; layer++)
{
osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,0);
UVs->push_back(vertex0._uv);
if (vertex0.validUV(layer))
{
osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,layer);
UVs->push_back(vertex0._uv[layer]);
}
}
}
@@ -221,37 +205,37 @@ protected:
virtual void readRecord(RecordInputStream& in, Document& document)
{
std::string id = in.readString(8);
_IRColor = in.readInt32();
_relativePriority = in.readInt16();
int32 IRColor = in.readInt32();
int16 relativePriority = in.readInt16();
_drawFlag = in.readUInt8();
_texturedWhite = in.readUInt8();
_primaryNameIndex = in.readInt16(-1);
_secondaryNameIndex = in.readInt16(-1);
uint8 texturedWhite = in.readUInt8();
int16 primaryNameIndex = in.readInt16(-1);
int16 secondaryNameIndex = in.readInt16(-1);
in.forward(1);
_template = in.readUInt8(FIXED_NO_ALPHA_BLENDING);
_detailTexture = in.readInt16(-1);
_textureIndex = in.readInt16(-1);
_materialIndex = in.readInt16(-1);
_surface = in.readInt16();
_feature = in.readInt16();
_IRMaterial = in.readInt32(-1);
int detailTexture = in.readInt16(-1);
int textureIndex = in.readInt16(-1);
int materialIndex = in.readInt16(-1);
int16 surface = in.readInt16();
int16 feature = in.readInt16();
int32 IRMaterial = in.readInt32(-1);
_transparency = in.readUInt16(0);
// version > 13
_influenceLOD = in.readUInt8();
_linestyle = in.readUInt8();
uint8 influenceLOD = in.readUInt8();
uint8 linestyle = in.readUInt8();
_flags = in.readUInt32(0);
_lightMode = in.readUInt8(FACE_COLOR);
in.forward(7);
_primaryPackedColor = in.readColor32();
_secondaryPackedColor = in.readColor32();
osg::Vec4 primaryPackedColor = in.readColor32();
osg::Vec4 secondaryPackedColor = in.readColor32();
// version >= VERSION_15_1
_textureMappingIndex = in.readInt16(-1);
int textureMappingIndex = in.readInt16(-1);
in.forward(2);
_primaryColorIndex = in.readInt32(-1);
_alternateColorIndex = in.readInt32(-1);
int primaryColorIndex = in.readInt32(-1);
int alternateColorIndex = in.readInt32(-1);
// version >= 16
in.forward(2);
_shaderIndex = in.readInt16(-1);
int shaderIndex = in.readInt16(-1);
// Create Geode or Billboard.
switch (_template)
@@ -289,7 +273,7 @@ protected:
_geode->setNodeMask(0);
// Face color
if (_texturedWhite!=0 && _textureIndex>=0)
if (texturedWhite!=0 && textureIndex>=0)
{
_primaryColor = osg::Vec4(1,1,1,1);
}
@@ -297,15 +281,15 @@ protected:
{
if (packedColorMode())
{
_primaryColor = _primaryPackedColor;
_primaryColor = primaryPackedColor;
}
else
{
if (document.version() < VERSION_15_1)
_primaryColor = document.getColorPool()->getColor(_primaryNameIndex);
_primaryColor = document.getColorPool()->getColor(primaryNameIndex);
else // >= VERSION_15_1
_primaryColor = document.getColorPool()->getColor(_primaryColorIndex);
_primaryColor = document.getColorPool()->getColor(primaryColorIndex);
}
}
@@ -318,23 +302,23 @@ protected:
{
osg::Vec4 col = _primaryColor;
col.a() = 1.0f - getTransparency();
osg::Material* material = document.getOrCreateMaterialPool()->getOrCreateMaterial(_materialIndex,col);
osg::Material* material = document.getOrCreateMaterialPool()->getOrCreateMaterial(materialIndex,col);
stateset->setAttribute(material);
isTransparentMaterial = material->getDiffuse(osg::Material::FRONT).a() < 0.99f;
}
// Shaders
if (_shaderIndex >= 0)
if (shaderIndex >= 0)
{
ShaderPool* sp = document.getOrCreateShaderPool();
osg::Program* program = sp->get(_shaderIndex);
osg::Program* program = sp->get(shaderIndex);
if (program)
stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
}
// Texture
TexturePool* tp = document.getOrCreateTexturePool();
osg::StateSet* textureStateSet = tp->get(_textureIndex);
osg::StateSet* textureStateSet = tp->get(textureIndex);
if (textureStateSet)
{
// Merge face stateset with texture stateset
@@ -390,14 +374,14 @@ protected:
stateset->setRenderBinDetails(document.subfaceLevel(),"RenderBin");
}
#if 1
// A simple share stateset optimization.
static osg::ref_ptr<osg::StateSet> lastStateset;
if (lastStateset.valid() && (stateset->compare(*lastStateset,false)==0))
stateset = lastStateset;
else
lastStateset = stateset;
#endif
_geode->setStateSet(stateset.get());
// Add to parent.
@@ -485,20 +469,19 @@ protected:
};
RegisterRecordProxy<Face> g_Face(FACE_OP);
RegisterRecordProxy<Face> g_Mesh(MESH_OP);
/** VertexList -
* The VertexList is a leaf record.
* Possible parents: Face, Mesh & LightPoint
*/
class VertexList : public PrimaryRecord
class VertexListRecord : public PrimaryRecord
{
public:
VertexList() {}
VertexListRecord() {}
META_Record(VertexList)
META_Record(VertexListRecord)
virtual void addVertex(Vertex& vertex)
{
@@ -516,7 +499,7 @@ public:
protected:
virtual ~VertexList() {}
virtual ~VertexListRecord() {}
virtual void readRecord(RecordInputStream& in, Document& document)
{
@@ -541,7 +524,7 @@ protected:
};
RegisterRecordProxy<VertexList> g_VertexList(VERTEX_LIST_OP);
RegisterRecordProxy<VertexListRecord> g_VertexList(VERTEX_LIST_OP);
/** MorphVertexList -
@@ -630,16 +613,538 @@ protected:
RegisterRecordProxy<MorphVertexList> g_MorphVertexList(MORPH_VERTEX_LIST_OP);
/* Mesh record
*/
class Mesh : public PrimaryRecord
{
// flags
static const unsigned int TERRAIN_BIT = 0x80000000u >> 0;
static const unsigned int NO_COLOR_BIT = 0x80000000u >> 1;
static const unsigned int NO_ALT_COLOR_BIT = 0x80000000u >> 2;
static const unsigned int PACKED_COLOR_BIT = 0x80000000u >> 3;
static const unsigned int FOOTPRINT_BIT = 0x80000000u >> 4; // Terrain culture cutout
static const unsigned int HIDDEN_BIT = 0x80000000u >> 5;
static const unsigned int ROOFLINE_BIT = 0x80000000u >> 6;
osg::Vec4 _primaryColor;
uint8 _drawFlag;
uint8 _template;
uint16 _transparency;
uint32 _flags;
uint8 _lightMode;
osg::ref_ptr<osg::Geode> _geode;
osg::ref_ptr<osg::Geometry> _geometry;
public:
Mesh() :
_primaryColor(1,1,1,1)
{
}
META_Record(Mesh)
META_setID(_geode)
META_setComment(_geode)
META_setMatrix(_geode)
META_setMultitexture(_geode)
// draw mode
enum DrawMode
{
SOLID_BACKFACED = 0,
SOLID_NO_BACKFACE = 1,
WIREFRAME_CLOSED = 2,
WIREFRAME_NOT_CLOSED = 3,
SURROUND_ALTERNATE_COLOR = 4,
OMNIDIRECTIONAL_LIGHT = 8,
UNIDIRECTIONAL_LIGHT = 9,
BIDIRECTIONAL_LIGHT = 10
};
inline DrawMode getDrawMode() const { return (DrawMode)_drawFlag; }
// lighting
enum LightMode
{
FACE_COLOR = 0,
VERTEX_COLOR = 1,
FACE_COLOR_LIGHTING = 2,
VERTEX_COLOR_LIGHTING = 3
};
inline LightMode getLightMode() const { return (LightMode)_lightMode; }
inline bool isLit() const { return (_lightMode==FACE_COLOR_LIGHTING) || (_lightMode==VERTEX_COLOR_LIGHTING); }
inline bool isGouraud() const { return (_lightMode==VERTEX_COLOR) || (_lightMode==VERTEX_COLOR_LIGHTING); }
// flags
inline bool noColor() const { return (_flags & NO_COLOR_BIT)!=0; }
inline bool isHidden() const { return (_flags & HIDDEN_BIT)!=0; }
inline bool isTerrain() const { return (_flags & TERRAIN_BIT)!=0; }
inline bool isFootprint() const { return (_flags & FOOTPRINT_BIT)!=0; }
inline bool isRoofline() const { return (_flags & ROOFLINE_BIT)!=0; }
inline bool packedColorMode() const { return (_flags & PACKED_COLOR_BIT)!=0; }
// billboard
enum TemplateMode
{
FIXED_NO_ALPHA_BLENDING = 0,
FIXED_ALPHA_BLENDING = 1,
AXIAL_ROTATE_WITH_ALPHA_BLENDING = 2,
POINT_ROTATE_WITH_ALPHA_BLENDING = 4
};
inline TemplateMode getTemplateMode() const { return (TemplateMode)_template; }
// transparency & alpha
inline bool isAlphaBlend() const
{
return (_template==FIXED_ALPHA_BLENDING) ||
(_template==AXIAL_ROTATE_WITH_ALPHA_BLENDING) ||
(_template==POINT_ROTATE_WITH_ALPHA_BLENDING);
}
inline osg::Vec4 getPrimaryColor() const { return _primaryColor; }
inline float getTransparency() const { return (float)_transparency / 65535.0f; }
inline bool isTransparent() const { return _transparency > 0; }
virtual void addChild(osg::Node& child)
{
// Add subface to parent.
if (_parent.valid())
_parent->addChild(child);
}
virtual void addGeometry(osg::Geometry& geometry)
{
_geode->addDrawable(&geometry);
}
protected:
virtual void readRecord(RecordInputStream& in, Document& document)
{
std::string id = in.readString(8);
in.forward(4);
int32 IRColor = in.readInt32();
int16 relativePriority = in.readInt16();
_drawFlag = in.readUInt8();
uint8 texturedWhite = in.readUInt8();
int16 primaryNameIndex = in.readInt16(-1);
int16 secondaryNameIndex = in.readInt16(-1);
in.forward(1);
_template = in.readUInt8(FIXED_NO_ALPHA_BLENDING);
int detailTexture = in.readInt16(-1);
int textureIndex = in.readInt16(-1);
int materialIndex = in.readInt16(-1);
int16 surface = in.readInt16();
int16 feature = in.readInt16();
int32 IRMaterial = in.readInt32(-1);
_transparency = in.readUInt16(0);
// version > 13
uint8 influenceLOD = in.readUInt8();
uint8 linestyle = in.readUInt8();
_flags = in.readUInt32(0);
_lightMode = in.readUInt8(FACE_COLOR);
in.forward(7);
osg::Vec4 primaryPackedColor = in.readColor32();
osg::Vec4 secondaryPackedColor = in.readColor32();
// version >= VERSION_15_1
int textureMappingIndex = in.readInt16(-1);
in.forward(2);
int primaryColorIndex = in.readInt32(-1);
int alternateColorIndex = in.readInt32(-1);
// version >= 16
in.forward(2);
int shaderIndex = in.readInt16(-1);
// Create Geode or Billboard.
switch (_template)
{
case AXIAL_ROTATE_WITH_ALPHA_BLENDING:
{
osg::Billboard* billboard = new osg::Billboard;
billboard->setMode(osg::Billboard::AXIAL_ROT);
_geode = billboard;
}
break;
case POINT_ROTATE_WITH_ALPHA_BLENDING:
{
osg::Billboard* billboard = new osg::Billboard;
billboard->setMode(osg::Billboard::POINT_ROT_WORLD);
_geode = billboard;
}
break;
default:
_geode = new osg::Geode;
}
_geode->setDataVariance(osg::Object::STATIC);
_geode->setName(id);
// StateSet
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
// Hidden
if (isHidden())
_geode->setNodeMask(0);
// Face color
if (texturedWhite!=0 && textureIndex>=0)
{
_primaryColor = osg::Vec4(1,1,1,1);
}
else
{
if (packedColorMode())
{
_primaryColor = primaryPackedColor;
}
else
{
if (document.version() < VERSION_15_1)
_primaryColor = document.getColorPool()->getColor(primaryNameIndex);
else // >= VERSION_15_1
_primaryColor = document.getColorPool()->getColor(primaryColorIndex);
}
}
// Lighting
stateset->setMode(GL_LIGHTING, isLit() ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
// Material
bool isTransparentMaterial = false;
if (isLit())
{
osg::Vec4 col = _primaryColor;
col.a() = 1.0f - getTransparency();
osg::Material* material = document.getOrCreateMaterialPool()->getOrCreateMaterial(materialIndex,col);
stateset->setAttribute(material);
isTransparentMaterial = material->getDiffuse(osg::Material::FRONT).a() < 0.99f;
}
// Shaders
if (shaderIndex >= 0)
{
ShaderPool* sp = document.getOrCreateShaderPool();
osg::Program* program = sp->get(shaderIndex);
if (program)
stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
}
// Texture
TexturePool* tp = document.getOrCreateTexturePool();
osg::StateSet* textureStateSet = tp->get(textureIndex);
if (textureStateSet)
{
// Merge face stateset with texture stateset
stateset->merge(*textureStateSet);
}
// Translucent image?
bool isImageTranslucent = false;
if (textureStateSet)
{
if (document.getUseTextureAlphaForTransparancyBinning())
{
osg::Texture2D* texture = dynamic_cast<osg::Texture2D*>(textureStateSet->getTextureAttribute(0,osg::StateAttribute::TEXTURE));
if (texture)
{
osg::Image* image = texture->getImage();
if (image && image->isImageTranslucent())
isImageTranslucent = true;
}
}
}
// Enable alpha blend?
if (isAlphaBlend() || isTransparent() || isTransparentMaterial || isImageTranslucent)
{
static osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
stateset->setAttributeAndModes(blendFunc.get(), osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}
// Cull face
switch(_drawFlag)
{
case SOLID_BACKFACED: // Enable backface culling
{
static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
break;
}
case SOLID_NO_BACKFACE: // Disable backface culling
stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
break;
}
// Subface
if (document.subfaceLevel() > 0)
{
static osg::ref_ptr<osg::PolygonOffset> polygonOffset = new osg::PolygonOffset(-10.0f, -40.0f);
stateset->setAttributeAndModes(polygonOffset.get(), osg::StateAttribute::ON);
static osg::ref_ptr<osg::Depth> depth = new osg::Depth(osg::Depth::LESS, 0.0, 1.0,false);
stateset->setAttribute(depth.get());
stateset->setRenderBinDetails(document.subfaceLevel(),"RenderBin");
}
// A simple share stateset optimization.
static osg::ref_ptr<osg::StateSet> lastStateset;
if (lastStateset.valid() && (stateset->compare(*lastStateset,false)==0))
stateset = lastStateset;
else
lastStateset = stateset;
_geode->setStateSet(stateset.get());
// Add to parent.
if (_parent.valid())
_parent->addChild(*_geode);
}
virtual ~Mesh() {}
};
RegisterRecordProxy<Mesh> g_Mesh(MESH_OP);
/** LocalVertexPool -
*/
class LocalVertexPool : public Record
{
// Attribute Mask
static const unsigned int HAS_POSITION = 0x80000000u >> 0;
static const unsigned int HAS_COLOR_INDEX = 0x80000000u >> 1;
static const unsigned int HAS_RGBA_COLOR = 0x80000000u >> 2;
static const unsigned int HAS_NORMAL = 0x80000000u >> 3;
static const unsigned int HAS_BASE_UV = 0x80000000u >> 4;
static const unsigned int HAS_UV_LAYER1 = 0x80000000u >> 5;
static const unsigned int HAS_UV_LAYER2 = 0x80000000u >> 6;
static const unsigned int HAS_UV_LAYER3 = 0x80000000u >> 7;
static const unsigned int HAS_UV_LAYER4 = 0x80000000u >> 8;
static const unsigned int HAS_UV_LAYER5 = 0x80000000u >> 9;
static const unsigned int HAS_UV_LAYER6 = 0x80000000u >> 10;
static const unsigned int HAS_UV_LAYER7 = 0x80000000u >> 11;
public:
LocalVertexPool() {}
META_Record(LocalVertexPool)
protected:
virtual ~LocalVertexPool() {}
virtual void readRecord(RecordInputStream& in, Document& document)
{
uint32 vertices = in.readUInt32();
uint32 mask = in.readUInt32();
osg::ref_ptr<VertexList> _vertexList = new VertexList(vertices);
for (unsigned int n=0; n<vertices; n++)
{
Vertex vertex;
if (mask & HAS_POSITION)
{
osg::Vec3d coord = in.readVec3d();
vertex.setCoord(coord*document.unitScale());
}
if (mask & HAS_COLOR_INDEX)
{
uint32 alphaIndex = in.readUInt32();
int index = alphaIndex & 0x00ffffff;
uint8 alpha = alphaIndex >> 24;
osg::Vec4 color = document.getColorPool()->getColor(index);
color.a() = (float)alpha/255;
vertex.setColor(color);
}
if (mask & HAS_RGBA_COLOR)
{
osg::Vec4f color = in.readColor32();
vertex.setColor(color);
}
if (mask & HAS_NORMAL)
{
osg::Vec3f normal = in.readVec3f();
vertex.setNormal(normal);
}
for (unsigned int layer=0; layer<8; layer++)
{
if (mask & (HAS_BASE_UV >> layer))
{
osg::Vec2f uv = in.readVec2f();
vertex.setUV(layer,uv);
}
}
(*_vertexList)[n] = vertex;
}
if (_parent.valid())
_parent->setLocalVertexPool(_vertexList.get());
}
};
RegisterRecordProxy<LocalVertexPool> g_LocalVertexPool(LOCAL_VERTEX_POOL_OP);
/** MeshPrimitive -
*/
class MeshPrimitive : public PrimaryRecord
{
enum PrimitiveType
{
TRIANGLE_STRIP = 1,
TRIANGLE_FAN = 2,
QUADRILATERAL_STRIP = 3,
INDEXED_POLYGON = 4
};
public:
MeshPrimitive() {}
META_Record(MeshPrimitive)
protected:
virtual ~MeshPrimitive() {}
virtual void readRecord(RecordInputStream& in, Document& document)
{
Mesh* mesh = dynamic_cast<Mesh*>(_parent.get());
if (!mesh) return;
VertexList* vertexList = mesh->getLocalVertexPool();
if (!vertexList) return;
int16 type = in.readInt16();
uint16 indexSize = in.readUInt16();
uint32 vertexCount = in.readUInt32();
GLenum mode = 0;
switch(type)
{
case TRIANGLE_STRIP:
mode = osg::PrimitiveSet::TRIANGLE_STRIP;
break;
case TRIANGLE_FAN:
mode = osg::PrimitiveSet::TRIANGLE_FAN;
break;
case QUADRILATERAL_STRIP:
mode = osg::PrimitiveSet::QUAD_STRIP;
break;
case INDEXED_POLYGON:
mode = osg::PrimitiveSet::POLYGON;
break;
}
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
geometry->addPrimitiveSet(new osg::DrawArrays(mode,0,vertexCount));
for (unsigned int n=0; n<vertexCount; n++)
{
unsigned int index = 0;
switch (indexSize)
{
case 1:
index = in.readUInt8();
break;
case 2:
index = in.readUInt16();
break;
case 4:
index = in.readUInt32();
break;
}
if (index < vertexList->size())
{
Vertex& vertex = (*vertexList)[index];
osg::Vec3Array* vertices = getOrCreateVertexArray(*geometry);
vertices->push_back(vertex._coord);
if (vertex.validColor())
{
osg::Vec4Array* colors = getOrCreateColorArray(*geometry);
colors->push_back(vertex._color);
}
if (vertex.validNormal())
{
osg::Vec3Array* normals = getOrCreateNormalArray(*geometry);
normals->push_back(vertex._normal);
}
for (int layer=0; layer<Vertex::MAX_LAYERS; layer++)
{
if (vertex.validUV(layer))
{
osg::Vec2Array* UVs = getOrCreateTextureArray(*geometry,layer);
UVs->push_back(vertex._uv[layer]);
}
}
}
}
// Color binding
if (mesh->isGouraud())
{
// Color per vertex
geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
}
else
{
// Color per face
osg::Vec4 col = mesh->getPrimaryColor();
col[3] = 1.0f - mesh->getTransparency();
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
osg::Vec4Array* colors = new osg::Vec4Array(1);
(*colors)[0] = col;
geometry->setColorArray(colors);
}
// Normal binding
if (mesh->isLit())
{
geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX );
}
else
{
geometry->setNormalBinding(osg::Geometry::BIND_OFF);
geometry->setNormalArray(NULL);
}
mesh->addGeometry(*geometry);
}
};
RegisterRecordProxy<MeshPrimitive> g_MeshPrimitive(MESH_PRIMITIVE_OP);
} // end namespace

View File

@@ -9,6 +9,7 @@
#include <osg/ProxyNode>
#include <osg/Sequence>
#include <osg/LOD>
#include <osg/ProxyNode>
#include <osgDB/FileUtils>
#include <osgSim/DOFTransform>
#include <osgSim/MultiSwitch>
@@ -587,7 +588,7 @@ RegisterRecordProxy<Switch> g_Switch(SWITCH_OP);
*/
class ExternalReference : public PrimaryRecord
{
osg::ref_ptr<osg::Group> _external;
osg::ref_ptr<osg::ProxyNode> _external;
public:
@@ -609,18 +610,9 @@ protected:
{
std::string strFile = in.readString(200);
//Path for Nested external references
const osgDB::ReaderWriter::Options *options = document.getOptions();
std::string filename = osgDB::findDataFile(strFile, options);
if (filename.empty())
{
osg::notify(osg::WARN) << "Can't find external " << strFile << std::endl;
return;
}
_external = new osg::Group;
_external->setName(strFile);
Registry::instance()->addExternal(filename, _external.get());
_external = new osg::ProxyNode;
_external->setCenterMode(osg::ProxyNode::USE_BOUNDING_SPHERE_CENTER);
_external->setFileName(0,strFile);
// Add this implementation to parent implementation.
if (_parent.valid())
@@ -761,3 +753,6 @@ RegisterRecordProxy<Extension> g_Extension(EXTENSION_OP);

View File

@@ -6,14 +6,13 @@
#include <stdexcept>
#include <osg/Notify>
#include <osg/ProxyNode>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/ReentrantMutex>
#include <osgSim/OpenFlightOptimizer>
#include "Registry.h"
#include "Document.h"
#include "RecordInputStream.h"
@@ -25,6 +24,35 @@ using namespace osg;
using namespace osgDB;
class ReadExternalsVisitor : public osg::NodeVisitor
{
osg::ref_ptr<ReaderWriter::Options> _options;
public:
ReadExternalsVisitor(ReaderWriter::Options* options) :
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_options(options)
{
}
virtual ~ReadExternalsVisitor() {}
virtual void apply(ProxyNode& node)
{
for (unsigned int pos=0; pos<node.getNumFileNames(); pos++)
{
std::string filename = node.getFileName(pos);
// read external
osg::Node* external = osgDB::readNodeFile(filename,_options.get());
if (external)
node.addChild(external);
}
}
};
class FLTReaderWriter : public ReaderWriter
{
public:
@@ -47,18 +75,55 @@ class FLTReaderWriter : public ReaderWriter
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile( file, options );
std::string fileName = osgDB::findDataFile(file, options);
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
// code for setting up the database path so that internally referenced file are searched for on relative paths.
// in local cache?
{
osg::Node* node = flt::Registry::instance()->getFromLocalCache(fileName);
if (node)
return ReadResult(node, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
}
// setting up the database path so that internally referenced file are searched for on relative paths.
osg::ref_ptr<Options> local_opt = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
local_opt->setDatabasePath(osgDB::getFilePath(fileName));
std::ifstream istream;
istream.imbue(std::locale::classic());
istream.open(fileName.c_str(), std::ios::in | std::ios::binary);
ReadResult rr;
return readNode(istream,local_opt.get());
// read file
{
std::ifstream istream;
istream.imbue(std::locale::classic());
istream.open(fileName.c_str(), std::ios::in | std::ios::binary);
if (istream)
{
rr = readNode(istream,local_opt.get());
}
}
static int nestedExternalsLevel = 0;
if (rr.success())
{
// add to local cache.
flt::Registry::instance()->addToLocalCache(fileName,rr.getNode());
// read externals.
if (rr.getNode())
{
nestedExternalsLevel++;
ReadExternalsVisitor visitor(local_opt.get());
rr.getNode()->accept(visitor);
nestedExternalsLevel--;
}
}
// clear local cache.
if (nestedExternalsLevel==0)
flt::Registry::instance()->clearLocalCache();
return rr;
}
virtual ReadResult readObject(std::istream& fin, const Options* options) const
@@ -68,62 +133,45 @@ class FLTReaderWriter : public ReaderWriter
virtual ReadResult readNode(std::istream& fin, const Options* options) const
{
try
Document document;
document.setOptions(options);
// option string
if (options)
{
Document document;
document.setOptions(options);
document.setUseTextureAlphaForTransparancyBinning(options->getOptionString().find("noTextureAlphaForTransparancyBinning")==std::string::npos);
osg::notify(osg::DEBUG_INFO) << "FltFile.getUseTextureAlphaForTransparancyBinning()=" << document.getUseTextureAlphaForTransparancyBinning() << std::endl;
document.setDoUnitsConversion((options->getOptionString().find("noUnitsConversion")==std::string::npos)); // default to true, unless noUnitsConversion is specified.o
osg::notify(osg::DEBUG_INFO) << "FltFile.getDoUnitsConversion()=" << document.getDoUnitsConversion() << std::endl;
// option string
if (options)
if (document.getDoUnitsConversion())
{
document.setUseTextureAlphaForTransparancyBinning(options->getOptionString().find("noTextureAlphaForTransparancyBinning")==std::string::npos);
osg::notify(osg::DEBUG_INFO) << "FltFile.getUseTextureAlphaForTransparancyBinning()=" << document.getUseTextureAlphaForTransparancyBinning() << std::endl;
document.setDoUnitsConversion((options->getOptionString().find("noUnitsConversion")==std::string::npos)); // default to true, unless noUnitsConversion is specified.o
osg::notify(osg::DEBUG_INFO) << "FltFile.getDoUnitsConversion()=" << document.getDoUnitsConversion() << std::endl;
if (document.getDoUnitsConversion())
{
if (options->getOptionString().find("convertToFeet")!=std::string::npos)
document.setDesiredUnits(FEET);
else if (options->getOptionString().find("convertToInches")!=std::string::npos)
document.setDesiredUnits(INCHES);
else if (options->getOptionString().find("convertToMeters")!=std::string::npos)
document.setDesiredUnits(METERS);
else if (options->getOptionString().find("convertToKilometers")!=std::string::npos)
document.setDesiredUnits(KILOMETERS);
else if (options->getOptionString().find("convertToNauticalMiles")!=std::string::npos)
document.setDesiredUnits(NAUTICAL_MILES);
}
if (options->getOptionString().find("convertToFeet")!=std::string::npos)
document.setDesiredUnits(FEET);
else if (options->getOptionString().find("convertToInches")!=std::string::npos)
document.setDesiredUnits(INCHES);
else if (options->getOptionString().find("convertToMeters")!=std::string::npos)
document.setDesiredUnits(METERS);
else if (options->getOptionString().find("convertToKilometers")!=std::string::npos)
document.setDesiredUnits(KILOMETERS);
else if (options->getOptionString().find("convertToNauticalMiles")!=std::string::npos)
document.setDesiredUnits(NAUTICAL_MILES);
}
{
// read records
flt::RecordInputStream recordStream(&fin);
while (recordStream().good() && !document.done())
{
recordStream.readRecord(document);
}
}
{
// optimize
osgFlightUtil::Optimizer optimizer;
optimizer.optimize(document.getHeaderNode());
}
readExternals(options);
return document.getHeaderNode();
}
catch (std::exception &e)
{
osg::notify(osg::NOTICE) << "Error reading file: " << e.what() << std::endl;
return ReadResult::FILE_NOT_HANDLED;
}
catch (...)
{
return ReadResult::FILE_NOT_HANDLED;
// read records
flt::RecordInputStream recordStream(&fin);
while (recordStream().good() && !document.done())
{
recordStream.readRecord(document);
}
}
if (!document.getHeaderNode())
return ReadResult::ERROR_IN_READING_FILE;
return document.getHeaderNode();
}
virtual WriteResult writeObject(const Object& object,const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
@@ -164,23 +212,6 @@ class FLTReaderWriter : public ReaderWriter
protected:
void readExternals(const Options* options) const
{
flt::Registry::ExternalQueue& eq = flt::Registry::instance()->getExternalQueue();
while (!eq.empty())
{
std::string extfilename = eq.front().first;
osg::ref_ptr<osg::Group> external = eq.front().second;
eq.pop();
if (external.valid())
{
osg::Node* extmodel = osgDB::readNodeFile(extfilename,options);
external->addChild(extmodel);
}
}
}
mutable osgDB::ReentrantMutex _serializerMutex;
};
@@ -199,3 +230,6 @@ RegisterReaderWriterProxy<FLTReaderWriter> g_FLTReaderWriterProxy;

View File

@@ -77,11 +77,15 @@ public:
void setNumberOfReplications(int num) { _numberOfReplications = num; }
void setLocalVertexPool(VertexList* pool) { _localVertexPool = pool; }
VertexList* getLocalVertexPool() { return _localVertexPool.get(); }
protected:
virtual ~PrimaryRecord() {}
int _numberOfReplications;
osg::ref_ptr<VertexList> _localVertexPool;
};

View File

@@ -8,6 +8,7 @@
#define FLT_REGISTRY_H 1
#include <queue>
#include <map>
#include <osg/ref_ptr>
#include "opcodes.h"
#include "Record.h"
@@ -21,31 +22,57 @@ class Registry : public osg::Referenced
~Registry();
static Registry* instance();
// Prototypes
// Record prototypes
void addPrototype(int opcode, Record* prototype);
Record* getPrototype(int opcode);
// Externals
typedef std::pair<std::string, osg::Group*> ExtNameNodePair;
typedef std::queue<ExtNameNodePair> ExternalQueue;
// External read queue
typedef std::pair<std::string, osg::Group*> FilenameParentPair; // ExtNameNodePair;
typedef std::queue<FilenameParentPair> ExternalQueue;
inline ExternalQueue& getExternalQueue() { return _externalQueue; }
inline ExternalQueue& getExternalReadQueue() { return _externalReadQueue; }
void addToExternalReadQueue(const std::string& filename, osg::Group* parent);
inline void addExternal(const std::string& name, osg::Group* node)
{
_externalQueue.push( ExtNameNodePair(name,node) );
}
// Local cache
void addToLocalCache(const std::string& filename, osg::Node* node);
osg::Node* getFromLocalCache(const std::string& filename);
void clearLocalCache();
protected:
Registry();
typedef std::map<int, osg::ref_ptr<Record> > RecordProtoMap;
RecordProtoMap _recordProtoMap;
RecordProtoMap _recordProtoMap;
ExternalQueue _externalQueue;
ExternalQueue _externalReadQueue;
typedef std::map<std::string, osg::ref_ptr<osg::Node> > ExternalCacheMap;
ExternalCacheMap _externalCacheMap;
};
inline void Registry::addToExternalReadQueue(const std::string& filename, osg::Group* parent)
{
_externalReadQueue.push( FilenameParentPair(filename,parent) );
}
inline void Registry::addToLocalCache(const std::string& filename, osg::Node* node)
{
_externalCacheMap[filename] = node;
}
inline osg::Node* Registry::getFromLocalCache(const std::string& filename)
{
ExternalCacheMap::iterator itr = _externalCacheMap.find(filename);
if (itr != _externalCacheMap.end())
return (*itr).second.get();
return NULL;
}
inline void Registry::clearLocalCache()
{
_externalCacheMap.clear();
}
/** Proxy class for automatic registration of reader/writers with the Registry.*/
template<class T>

View File

@@ -13,43 +13,50 @@ Vertex::Vertex():
_color(1,1,1,1),
_normal(0,0,1),
_validColor(false),
_validNormal(false),
_validUV(false)
_validNormal(false)
{
for (int layer=0; layer<MAX_LAYERS; layer++)
_validUV[layer] = false;
}
Vertex::Vertex(const Vertex& vertex):
_coord(vertex._coord),
_color(vertex._color),
_normal(vertex._normal),
_uv(vertex._uv),
_validColor(vertex._validColor),
_validNormal(vertex._validNormal),
_validUV(vertex._validUV)
_validNormal(vertex._validNormal)
{
for (int layer=0; layer<MAX_LAYERS; layer++)
{
_uv[layer] = vertex._uv[layer];
_validUV[layer] = vertex._validUV[layer];
}
}
void Vertex::setCoord(osg::Vec3 coord)
void Vertex::setCoord(const osg::Vec3 coord)
{
_coord = coord;
}
void Vertex::setColor(osg::Vec4 color)
void Vertex::setColor(const osg::Vec4 color)
{
_color = color;
_validColor = true;
}
void Vertex::setNormal(osg::Vec3 normal)
void Vertex::setNormal(const osg::Vec3 normal)
{
_normal = normal;
_validNormal = true;
}
void Vertex::setUV(osg::Vec2 uv)
void Vertex::setUV(int layer, const osg::Vec2 uv)
{
_uv = uv;
_validUV = true;
if (layer>=0 && layer<MAX_LAYERS)
{
_uv[layer] = uv;
_validUV[layer] = true;
}
}

View File

@@ -7,9 +7,11 @@
#ifndef FLT_VERTEX_H
#define FLT_VERTEX_H 1
#include <vector>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Referenced>
namespace flt {
@@ -20,23 +22,40 @@ public:
Vertex();
Vertex(const Vertex& vertex);
void setCoord(osg::Vec3 coord);
void setColor(osg::Vec4 color);
void setNormal(osg::Vec3 normal);
void setUV(osg::Vec2 uv);
void setCoord(const osg::Vec3 coord);
void setColor(const osg::Vec4 color);
void setNormal(const osg::Vec3 normal);
void setUV(int layer, const osg::Vec2 uv);
bool validColor() const { return _validColor; }
bool validNormal() const { return _validNormal; }
bool validUV() const { return _validUV; }
bool validUV(int layer) const { return layer>=0 && layer<MAX_LAYERS && _validUV[layer]; }
static const int MAX_LAYERS = 8;
osg::Vec3 _coord;
osg::Vec4 _color;
osg::Vec3 _normal;
osg::Vec2 _uv;
osg::Vec2 _uv[MAX_LAYERS];
bool _validColor;
bool _validNormal;
bool _validUV;
bool _validUV[MAX_LAYERS];
};
class VertexList : public osg::Referenced , public std::vector<Vertex>
{
public:
VertexList() {}
explicit VertexList(int size) :
std::vector<Vertex>(size) {}
protected:
virtual ~VertexList() {}
};
} // end namespace

View File

@@ -128,7 +128,7 @@ class VertexCT : public Record
Vertex vertex;
vertex.setCoord(coord*document.unitScale());
vertex.setUV(uv);
vertex.setUV(0,uv);
// color
if (flags & PACKED_COLOR)
@@ -169,7 +169,7 @@ class VertexCNT : public Record
Vertex vertex;
vertex.setCoord(coord*document.unitScale());
vertex.setNormal(normal);
vertex.setUV(uv);
vertex.setUV(0,uv);
// color
if (flags & PACKED_COLOR)
@@ -215,7 +215,7 @@ class AbsoluteVertex : public Record
if (in().tellg() < in.getEndOfRecord())
{
osg::Vec2f uv = in.readVec2f();
vertex.setUV(uv);
vertex.setUV(0,uv);
}
if (_parent.valid())
@@ -263,7 +263,7 @@ class ShadedVertex : public Record
if (in().tellg() < in.getEndOfRecord())
{
osg::Vec2f uv = in.readVec2f();
vertex.setUV(uv);
vertex.setUV(0,uv);
}
if (_parent.valid())
@@ -311,7 +311,7 @@ class NormalVertex : public Record
if (in().tellg() < in.getEndOfRecord())
{
osg::Vec2f uv = in.readVec2f();
vertex.setUV(uv);
vertex.setUV(0,uv);
}
if (_parent.valid())