From 132b355d4f202f90461d413e61365e13681fcd31 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 15 May 2006 11:18:50 +0000 Subject: [PATCH] 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" --- src/osgPlugins/OpenFlight/GeometryRecords.cpp | 657 ++++++++++++++++-- src/osgPlugins/OpenFlight/PrimaryRecords.cpp | 21 +- src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp | 182 +++-- src/osgPlugins/OpenFlight/Record.h | 4 + src/osgPlugins/OpenFlight/Registry.h | 49 +- src/osgPlugins/OpenFlight/Vertex.cpp | 29 +- src/osgPlugins/OpenFlight/Vertex.h | 33 +- src/osgPlugins/OpenFlight/VertexRecords.cpp | 10 +- 8 files changed, 788 insertions(+), 197 deletions(-) diff --git a/src/osgPlugins/OpenFlight/GeometryRecords.cpp b/src/osgPlugins/OpenFlight/GeometryRecords.cpp index 9bb85b5fd..7b70062ac 100644 --- a/src/osgPlugins/OpenFlight/GeometryRecords.cpp +++ b/src/osgPlugins/OpenFlight/GeometryRecords.cpp @@ -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 _geode; osg::ref_ptr _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; layerpush_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; layerpush_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 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 g_Face(FACE_OP); -RegisterRecordProxy 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 g_VertexList(VERTEX_LIST_OP); +RegisterRecordProxy g_VertexList(VERTEX_LIST_OP); /** MorphVertexList - @@ -630,16 +613,538 @@ protected: RegisterRecordProxy 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 _geode; + osg::ref_ptr _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 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(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 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 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 polygonOffset = new osg::PolygonOffset(-10.0f, -40.0f); + stateset->setAttributeAndModes(polygonOffset.get(), osg::StateAttribute::ON); + + static osg::ref_ptr 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 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 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 = new VertexList(vertices); + + + for (unsigned int n=0; n> 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 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(_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 geometry = new osg::Geometry; + geometry->addPrimitiveSet(new osg::DrawArrays(mode,0,vertexCount)); + + for (unsigned int n=0; nsize()) + { + 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; layerpush_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 g_MeshPrimitive(MESH_PRIMITIVE_OP); + + } // end namespace - - - - - - - - diff --git a/src/osgPlugins/OpenFlight/PrimaryRecords.cpp b/src/osgPlugins/OpenFlight/PrimaryRecords.cpp index 7e4919d07..faa85b68e 100644 --- a/src/osgPlugins/OpenFlight/PrimaryRecords.cpp +++ b/src/osgPlugins/OpenFlight/PrimaryRecords.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -587,7 +588,7 @@ RegisterRecordProxy g_Switch(SWITCH_OP); */ class ExternalReference : public PrimaryRecord { - osg::ref_ptr _external; + osg::ref_ptr _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 g_Extension(EXTENSION_OP); + + + diff --git a/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp b/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp index a3cb46a0d..37d790af6 100644 --- a/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp +++ b/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp @@ -6,14 +6,13 @@ #include #include +#include #include #include #include #include #include -#include - #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 _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; posgetFromLocalCache(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 local_opt = options ? static_cast(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 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 g_FLTReaderWriterProxy; + + + diff --git a/src/osgPlugins/OpenFlight/Record.h b/src/osgPlugins/OpenFlight/Record.h index b68fe4fc5..1f0089537 100644 --- a/src/osgPlugins/OpenFlight/Record.h +++ b/src/osgPlugins/OpenFlight/Record.h @@ -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 _localVertexPool; }; diff --git a/src/osgPlugins/OpenFlight/Registry.h b/src/osgPlugins/OpenFlight/Registry.h index 32f79067b..fe65b6123 100644 --- a/src/osgPlugins/OpenFlight/Registry.h +++ b/src/osgPlugins/OpenFlight/Registry.h @@ -8,6 +8,7 @@ #define FLT_REGISTRY_H 1 #include +#include #include #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 ExtNameNodePair; - typedef std::queue ExternalQueue; + // External read queue + typedef std::pair FilenameParentPair; // ExtNameNodePair; + typedef std::queue 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 > RecordProtoMap; - RecordProtoMap _recordProtoMap; + RecordProtoMap _recordProtoMap; - ExternalQueue _externalQueue; + ExternalQueue _externalReadQueue; + + typedef std::map > 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 diff --git a/src/osgPlugins/OpenFlight/Vertex.cpp b/src/osgPlugins/OpenFlight/Vertex.cpp index 6678680c5..9f3f8fa6d 100644 --- a/src/osgPlugins/OpenFlight/Vertex.cpp +++ b/src/osgPlugins/OpenFlight/Vertex.cpp @@ -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=0 && layer #include #include #include +#include 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 +{ +public: + + VertexList() {} + + explicit VertexList(int size) : + std::vector(size) {} + +protected: + + virtual ~VertexList() {} }; } // end namespace diff --git a/src/osgPlugins/OpenFlight/VertexRecords.cpp b/src/osgPlugins/OpenFlight/VertexRecords.cpp index 8f13eb275..2e9a71fc4 100644 --- a/src/osgPlugins/OpenFlight/VertexRecords.cpp +++ b/src/osgPlugins/OpenFlight/VertexRecords.cpp @@ -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())