diff --git a/include/osgSim/MultiSwitch b/include/osgSim/MultiSwitch index d400279b6..7501e5d75 100644 --- a/include/osgSim/MultiSwitch +++ b/include/osgSim/MultiSwitch @@ -69,8 +69,9 @@ class OSGSIM_EXPORT MultiSwitch : public osg::Group /** Get which of the available switch set lists to use.*/ unsigned int getActiveSwitchSet() const { return _activeSwitchSet; } - typedef std::vector ValueList; - typedef std::vector SwitchSetList; + typedef std::vector ValueList; + typedef std::vector SwitchSetList; + typedef std::vector SwitchSetNameList; /** Set the compile set of different values.*/ void setSwitchSetList(const SwitchSetList& switchSetList); @@ -84,6 +85,10 @@ class OSGSIM_EXPORT MultiSwitch : public osg::Group /** Get the a single set of different values for a particular switch set.*/ const ValueList& getValueList(unsigned int switchSet) const { return _values[switchSet]; } + void setValueName(unsigned int switchSet, const std::string& name); + + const std::string& getValueName(unsigned int switchSet) const { return _valueNames[switchSet]; } + protected : virtual ~MultiSwitch() {} @@ -91,9 +96,10 @@ class OSGSIM_EXPORT MultiSwitch : public osg::Group void expandToEncompassSwitchSet(unsigned int switchSet); // this is effectively a list of bit mask. - bool _newChildDefaultValue; - unsigned int _activeSwitchSet; - SwitchSetList _values; + bool _newChildDefaultValue; + unsigned int _activeSwitchSet; + SwitchSetList _values; + SwitchSetNameList _valueNames; }; } diff --git a/src/osgPlugins/OpenFlight/AncillaryRecords.cpp b/src/osgPlugins/OpenFlight/AncillaryRecords.cpp index a5e7ffdef..fce52d9c6 100644 --- a/src/osgPlugins/OpenFlight/AncillaryRecords.cpp +++ b/src/osgPlugins/OpenFlight/AncillaryRecords.cpp @@ -316,6 +316,35 @@ class Replicate : public Record REGISTER_FLTRECORD(Replicate, REPLICATE_OP) + +/** IndexedString - + */ +class IndexedString : public Record +{ + public: + + IndexedString() {} + + META_Record(IndexedString) + + protected: + + virtual ~IndexedString() {} + + virtual void readRecord(RecordInputStream& in, Document& /*document*/) + { + std::streamsize size = in.getRecordSize(); + uint32 index = in.readUInt32(); + std::string name = in.readString(size-8); + + if (_parent.valid()) + _parent->setMultiSwitchValueName(index, name); + } +}; + +REGISTER_FLTRECORD(IndexedString, INDEXED_STRING_OP) + + // Prevent "unknown record" message for the following ancillary records: REGISTER_FLTRECORD(DummyRecord, OLD_TRANSLATE2_OP) REGISTER_FLTRECORD(DummyRecord, OLD_ROTATE_ABOUT_POINT_OP) @@ -327,7 +356,6 @@ REGISTER_FLTRECORD(DummyRecord, OLD_ROTATE_ABOUT_POINT2_OP) REGISTER_FLTRECORD(DummyRecord, OLD_ROTATE_SCALE_TO_POINT_OP) REGISTER_FLTRECORD(DummyRecord, OLD_PUT_TRANSFORM_OP) REGISTER_FLTRECORD(DummyRecord, OLD_BOUNDING_BOX_OP) -REGISTER_FLTRECORD(DummyRecord, INDEXED_STRING_OP) REGISTER_FLTRECORD(DummyRecord, ROAD_ZONE_OP) REGISTER_FLTRECORD(DummyRecord, ROTATE_ABOUT_EDGE_OP) REGISTER_FLTRECORD(DummyRecord, TRANSLATE_OP) diff --git a/src/osgPlugins/OpenFlight/CMakeLists.txt b/src/osgPlugins/OpenFlight/CMakeLists.txt index c29293fce..f446368a9 100644 --- a/src/osgPlugins/OpenFlight/CMakeLists.txt +++ b/src/osgPlugins/OpenFlight/CMakeLists.txt @@ -1,6 +1,3 @@ -#this file is automatically generated - - SET(TARGET_SRC AncillaryRecords.cpp AttrData.cpp diff --git a/src/osgPlugins/OpenFlight/Document.cpp b/src/osgPlugins/OpenFlight/Document.cpp index dc02d9095..d6fee5df6 100644 --- a/src/osgPlugins/OpenFlight/Document.cpp +++ b/src/osgPlugins/OpenFlight/Document.cpp @@ -26,6 +26,7 @@ Document::Document() : _replaceClampWithClampToEdge(false), _preserveFace(false), _preserveObject(false), + _replaceDoubleSidedPolys(false), _defaultDOFAnimationState(false), _useTextureAlphaForTransparancyBinning(true), _useBillboardCenter(false), @@ -83,7 +84,7 @@ void Document::pushExtension() { if (!_currentPrimaryRecord.valid()) { - osg::notify(osg::WARN) << "No current primary in Document::pushExtension()." << std::endl; + OSG_WARN << "No current primary in Document::pushExtension()." << std::endl; return; } @@ -95,7 +96,7 @@ void Document::popExtension() _currentPrimaryRecord=_extensionStack.back().get(); if (!_currentPrimaryRecord.valid()) { - osg::notify(osg::WARN) << "Can't decide primary in Document::popExtension()." << std::endl; + OSG_WARN << "Can't decide primary in Document::popExtension()." << std::endl; return; } @@ -118,7 +119,7 @@ void Document::setSubSurfacePolygonOffset(int level, osg::PolygonOffset* po) osg::PolygonOffset* Document::getSubSurfacePolygonOffset(int level) { - osg::notify(osg::DEBUG_INFO)<<"Document::getSubSurfacePolygonOffset("<& po = _subsurfacePolygonOffsets[level]; if (!po) { diff --git a/src/osgPlugins/OpenFlight/Document.h b/src/osgPlugins/OpenFlight/Document.h index 60c963b2d..ac9f08adc 100644 --- a/src/osgPlugins/OpenFlight/Document.h +++ b/src/osgPlugins/OpenFlight/Document.h @@ -182,6 +182,8 @@ class Document bool getPreserveFace() const { return _preserveFace; } void setPreserveObject(bool flag) { _preserveObject = flag; } bool getPreserveObject() const { return _preserveObject; } + void setReplaceDoubleSidedPolys(bool flag) { _replaceDoubleSidedPolys = flag; } + bool getReplaceDoubleSidedPolys() const { return _replaceDoubleSidedPolys; } void setDefaultDOFAnimationState(bool state) { _defaultDOFAnimationState = state; } bool getDefaultDOFAnimationState() const { return _defaultDOFAnimationState; } void setUseTextureAlphaForTransparancyBinning(bool flag) { _useTextureAlphaForTransparancyBinning=flag; } @@ -206,6 +208,7 @@ class Document bool _replaceClampWithClampToEdge; bool _preserveFace; bool _preserveObject; + bool _replaceDoubleSidedPolys; bool _defaultDOFAnimationState; bool _useTextureAlphaForTransparancyBinning; bool _useBillboardCenter; diff --git a/src/osgPlugins/OpenFlight/ExportOptions.cpp b/src/osgPlugins/OpenFlight/ExportOptions.cpp index 80c278c5c..6adeb75e2 100644 --- a/src/osgPlugins/OpenFlight/ExportOptions.cpp +++ b/src/osgPlugins/OpenFlight/ExportOptions.cpp @@ -153,20 +153,20 @@ ExportOptions::parseOptionsString() // See if it's a Boolen/toggle if ( token == _validateOption ) { - osg::notify( osg::INFO ) << "fltexp: Found: " << token << std::endl; + OSG_INFO << "fltexp: Found: " << token << std::endl; setValidateOnly( true ); continue; } if ( token == _stripTextureFilePathOption ) { - osg::notify( osg::INFO ) << "fltexp: Found: " << token << std::endl; + OSG_INFO << "fltexp: Found: " << token << std::endl; setStripTextureFilePath( true ); continue; } // Protect against unrecognized options without values if ( pos == str.npos ) { - osg::notify( osg::WARN ) << "fltexp: Bogus OptionString: " << token << std::endl; + OSG_WARN << "fltexp: Bogus OptionString: " << token << std::endl; continue; } @@ -187,19 +187,19 @@ ExportOptions::parseOptionsString() if (token == _versionOption) { - osg::notify( osg::INFO ) << "fltexp: Token: " << token << ", Value: " << value << std::endl; + OSG_INFO << "fltexp: Token: " << token << ", Value: " << value << std::endl; int version( VERSION_16_1 ); if( value == std::string( "15.7" ) ) version = VERSION_15_7; else if( value == std::string( "15.8" ) ) version = VERSION_15_8; else if( value != std::string( "16.1" ) ) - osg::notify( osg::WARN ) << "fltexp: Unsupported version: " << value << ". Defaulting to 16.1." << std::endl; + OSG_WARN << "fltexp: Unsupported version: " << value << ". Defaulting to 16.1." << std::endl; setFlightFileVersionNumber( version ); } else if (token == _unitsOption) { - osg::notify( osg::INFO ) << "fltexp: Token: " << token << ", Value: " << value << std::endl; + OSG_INFO << "fltexp: Token: " << token << ", Value: " << value << std::endl; FlightUnits units( METERS ); if( value == std::string( "KILOMETERS" ) ) units = KILOMETERS; @@ -210,26 +210,26 @@ ExportOptions::parseOptionsString() else if( value == std::string( "NAUTICAL_MILES" ) ) units = NAUTICAL_MILES; else if( value != std::string( "METERS" ) ) - osg::notify( osg::WARN ) << "fltexp: Unsupported units: " << value << ". Defaulting to METERS." << std::endl; + OSG_WARN << "fltexp: Unsupported units: " << value << ". Defaulting to METERS." << std::endl; setFlightUnits( units ); } else if (token == _tempDirOption) { - osg::notify( osg::INFO ) << "fltexp: Token: " << token << ", Value: " << value << std::endl; + OSG_INFO << "fltexp: Token: " << token << ", Value: " << value << std::endl; setTempDir( value ); } else if (token == _lightingOption) { - osg::notify( osg::INFO ) << "fltexp: Token: " << token << ", Value: " << value << std::endl; + OSG_INFO << "fltexp: Token: " << token << ", Value: " << value << std::endl; bool lighting( true ); if (value == std::string( "OFF" ) ) lighting = false; else if (value != std::string( "ON" ) ) - osg::notify( osg::WARN ) << "fltexp: Unsupported lighting value: " << value << ". Defaulting to ON." << std::endl; + OSG_WARN << "fltexp: Unsupported lighting value: " << value << ". Defaulting to ON." << std::endl; setLightingDefault( lighting ); } else - osg::notify( osg::WARN ) << "fltexp: Bogus OptionString: " << token << std::endl; + OSG_WARN << "fltexp: Bogus OptionString: " << token << std::endl; } } diff --git a/src/osgPlugins/OpenFlight/ExportOptions.h b/src/osgPlugins/OpenFlight/ExportOptions.h index b1907bef3..99b5b54a2 100644 --- a/src/osgPlugins/OpenFlight/ExportOptions.h +++ b/src/osgPlugins/OpenFlight/ExportOptions.h @@ -21,7 +21,6 @@ #include #include -#include #include #include diff --git a/src/osgPlugins/OpenFlight/FltExportVisitor.cpp b/src/osgPlugins/OpenFlight/FltExportVisitor.cpp index 47e0db85c..a2fcf1719 100644 --- a/src/osgPlugins/OpenFlight/FltExportVisitor.cpp +++ b/src/osgPlugins/OpenFlight/FltExportVisitor.cpp @@ -117,12 +117,12 @@ FltExportVisitor::~FltExportVisitor() // Delete our temp file. if (_recordsStr.is_open()) { - osg::notify( osg::WARN ) << "fltexp: FltExportVisitor destructor has an open temp file." << std::endl; + OSG_WARN << "fltexp: FltExportVisitor destructor has an open temp file." << std::endl; // This should not happen. FltExportVisitor::complete should close // this file before we get to this destructor. return; } - osg::notify( osg::INFO ) << "fltexp: Deleting temp file " << _recordsTempName << std::endl; + OSG_INFO << "fltexp: Deleting temp file " << _recordsTempName << std::endl; FLTEXP_DELETEFILE( _recordsTempName.c_str() ); } @@ -356,7 +356,7 @@ FltExportVisitor::apply( osg::Geode& node ) if (!geom) { std::string warning( "fltexp: Non-Geometry Drawable encountered. Ignoring." ); - osg::notify( osg::WARN ) << warning << std::endl; + OSG_WARN << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); continue; } @@ -391,7 +391,7 @@ FltExportVisitor::apply( osg::Geode& node ) else { std::string warning( "fltexp: Unknown PrimitiveSet type." ); - osg::notify( osg::WARN ) << warning << std::endl; + OSG_WARN << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; } @@ -429,7 +429,7 @@ FltExportVisitor::apply( osg::Geode& node ) else { std::string warning( "fltexp: Unknown PrimitiveSet type." ); - osg::notify( osg::WARN ) << warning << std::endl; + OSG_WARN << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; } @@ -461,7 +461,7 @@ FltExportVisitor::apply( osg::Node& node ) // would export a Group record then continue traversal. Because we are // a Node, there's no way to continue traversal, so just return.) std::string warning( "fltexp: Unknown Node in OpenFlight export." ); - osg::notify( osg::WARN ) << warning << std::endl; + OSG_WARN << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; } diff --git a/src/osgPlugins/OpenFlight/FltExportVisitor.h b/src/osgPlugins/OpenFlight/FltExportVisitor.h index 21d2e4161..0a89aa978 100644 --- a/src/osgPlugins/OpenFlight/FltExportVisitor.h +++ b/src/osgPlugins/OpenFlight/FltExportVisitor.h @@ -136,7 +136,8 @@ public: void writeMeshPrimitive( const std::vector& indices, GLenum mode ); void writeLocalVertexPool( const osg::Geometry& geom ); void writeMultitexture( const osg::Geometry& geom ); - void writeUVList( int numVerts, const osg::Geometry& geom ); + void writeUVList( int numVerts, const osg::Geometry& geom, const std::vector& indices ); + void writeUVList( int numVerts, const osg::Geometry& geom, unsigned int first=0); // Light Point records void writeLightPoint(); diff --git a/src/osgPlugins/OpenFlight/GeometryRecords.cpp b/src/osgPlugins/OpenFlight/GeometryRecords.cpp index fddfd69e1..a943185c7 100644 --- a/src/osgPlugins/OpenFlight/GeometryRecords.cpp +++ b/src/osgPlugins/OpenFlight/GeometryRecords.cpp @@ -29,8 +29,108 @@ #include "Document.h" #include "RecordInputStream.h" +#include + namespace flt { +template +void reverseWindingOrder( ARRAY* data, GLenum mode, GLint first, GLint last ) +{ + switch( mode ) + { + case osg::PrimitiveSet::TRIANGLES: + case osg::PrimitiveSet::QUADS: + case osg::PrimitiveSet::POLYGON: + // reverse all the vertices. + std::reverse(data->begin()+first, data->begin()+last); + break; + case osg::PrimitiveSet::TRIANGLE_STRIP: + case osg::PrimitiveSet::QUAD_STRIP: + // reverse only the shared edges. + for( GLint i = first; i < last-1; i+=2 ) + { + std::swap( (*data)[i], (*data)[i+1] ); + } + break; + case osg::PrimitiveSet::TRIANGLE_FAN: + // reverse all vertices except the first vertex. + std::reverse(data->begin()+first+1, data->begin()+last); + break; + } +} + +void addDrawableAndReverseWindingOrder( osg::Geode* geode ) +{ + // Replace double sided polygons by duplicating the drawables and inverting the normals. + std::vector new_drawables; + + for (size_t i=0; igetNumDrawables(); ++i) + { + const osg::Geometry* geometry = dynamic_cast(geode->getDrawable(i)); + if(geometry) + { + osg::Geometry* geom = new osg::Geometry(*geometry + , osg::CopyOp::DEEP_COPY_ARRAYS | osg::CopyOp::DEEP_COPY_PRIMITIVES); + new_drawables.push_back(geom); + + for( size_t i = 0; i < geom->getNumPrimitiveSets( ); ++i ) + { + osg::DrawArrays* drawarray = dynamic_cast( geom->getPrimitiveSet( i ) ); + if( drawarray ) + { + GLint first = drawarray->getFirst(); + GLint last = drawarray->getFirst()+drawarray->getCount(); + + // Invert vertex order. + osg::Vec3Array* vertices = dynamic_cast(geom->getVertexArray()); + if( vertices ) + { + reverseWindingOrder( vertices, drawarray->getMode(), first, last ); + } + + if( geom->getNormalBinding( ) == osg::Geometry::BIND_PER_VERTEX ) + { + osg::Vec3Array* normals = dynamic_cast(geom->getNormalArray()); + if( normals ) + { + // First, invert the direction of the normals. + for( GLint i = first; i < last; ++i ) + { + (*normals)[i] = -(*normals)[i]; + } + reverseWindingOrder( normals, drawarray->getMode(), first, last ); + } + } + + if( geom->getColorBinding( ) == osg::Geometry::BIND_PER_VERTEX ) + { + osg::Vec4Array* colors = dynamic_cast(geom->getColorArray()); + if( colors ) + { + reverseWindingOrder( colors, drawarray->getMode(), first, last ); + } + } + + for( size_t i = 0; i < geom->getNumTexCoordArrays(); ++i ) + { + osg::Vec2Array* UVs = dynamic_cast(geom->getTexCoordArray(i)); + if( UVs ) + { + reverseWindingOrder( UVs, drawarray->getMode(), first, last ); + } + } + } + } + } + } + + // Now add the new geometry drawable. + for( size_t i = 0; i < new_drawables.size( ); ++i ) + { + geode->addDrawable( new_drawables[i] ); + } +} + /* Face record */ class Face : public PrimaryRecord @@ -374,7 +474,15 @@ protected: break; } case SOLID_NO_BACKFACE: // Disable backface culling - stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); + if( document.getReplaceDoubleSidedPolys( ) ) + { + static osg::ref_ptr cullFace = new osg::CullFace(osg::CullFace::BACK); + stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON); + } + else + { + stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); + } break; } @@ -477,6 +585,11 @@ protected: } } + if( getDrawMode( ) == SOLID_NO_BACKFACE && document.getReplaceDoubleSidedPolys( ) ) + { + addDrawableAndReverseWindingOrder( _geode.get() ); + } + osg::StateSet* stateset = _geode->getOrCreateStateSet(); // Translucent image? @@ -930,7 +1043,15 @@ protected: break; } case SOLID_NO_BACKFACE: // Disable backface culling - stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); + if( document.getReplaceDoubleSidedPolys( ) ) + { + static osg::ref_ptr cullFace = new osg::CullFace(osg::CullFace::BACK); + stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON); + } + else + { + stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); + } break; } @@ -960,6 +1081,11 @@ protected: insertMatrixTransform(*_geode,*_matrix,_numberOfReplications); } + if( getDrawMode( ) == SOLID_NO_BACKFACE && document.getReplaceDoubleSidedPolys( ) ) + { + addDrawableAndReverseWindingOrder( _geode.get() ); + } + osg::StateSet* stateset = _geode->getOrCreateStateSet(); // Translucent image? @@ -1072,7 +1198,7 @@ protected: if (!coord.valid()) { - osg::notify(osg::NOTICE)<<"Warning: data error detected in LocalVertexPool::readRecord coord="<set( originLat, originLong ); _header->setUserData( loc ); - osg::notify(osg::INFO) << "DB lat=" << originLat << " lon=" << originLong << std::endl; + OSG_INFO << "DB lat=" << originLat << " lon=" << originLong << std::endl; document.setHeaderNode(_header.get()); } @@ -200,7 +200,7 @@ protected: void readRecord(RecordInputStream& in, Document& document) { std::string id = in.readString(8); - osg::notify(osg::DEBUG_INFO) << "ID: " << id << std::endl; + OSG_DEBUG << "ID: " << id << std::endl; /*int16 relativePriority =*/ in.readInt16(); in.forward(2); @@ -396,10 +396,10 @@ protected: if ((length_x*length_y*length_z)==0.0f) { - osg::notify(osg::NOTICE)<<"Warning: OpenFlight DegreeOfFreedom::readRecord() found erroneous axis definition:"<", "Export option: Specifies the version of the output OpenFlight file. Supported values include 15.7, 15.8, and 16.1. Default is 16.1. Example: \"version=15.8\"." ); - supportsOption( "units=", "Export option: Specifies the contents of the Units field of the OpenFliht header record. Valid values include INCHES, FEET, METERS, KILOMETERS, and NATICAL_MILES. Default is METERS. Example: \"units=METERS\"." ); + supportsOption( "units=", "Export option: Specifies the contents of the Units field of the OpenFlight header record. Valid values include INCHES, FEET, METERS, KILOMETERS, and NAUTICAL_MILES. Default is METERS. Example: \"units=METERS\"." ); supportsOption( "validate", "Export option: If present in the Options string, the plugin does not write an OpenFlight file. Instead, it returns an indication of the scene graph's suitability for OpenFlight export." ); supportsOption( "tempDir=", "Export option: Specifies the directory to use for creation of temporary files. If not specified, the directory is taken from the file name. If the file doesn't contain a path, the current working directory is used. Applications should set this to the name of their app-specific temp directory. If the path contains spaces, use double quotes to ensure correct parsing. Examples: \"tempDir=/tmp\", \"tempDir=\"C:\\My Temp Dir\"." ); supportsOption( "lighting=", "Export option: Specifies a default enable/disable state for lighting, for Nodes in the exported scene graph that don't set it explicitly. By default, the exporter assumes lighting is enabled (GL_LIGHTING ON). Set this to either ON or OFF. Example: \"lighting=OFF\"." ); @@ -310,7 +311,7 @@ class FLTReaderWriter : public ReaderWriter if ( !keepExternalReferences ) { - osg::notify(osg::DEBUG_INFO) << "keepExternalReferences not found, so externals will be re-readed"<getOptionString().find("clampToEdge")!=std::string::npos)); - osg::notify(osg::DEBUG_INFO) << readerMsg << "clampToEdge=" << document.getReplaceClampWithClampToEdge() << std::endl; + OSG_DEBUG << readerMsg << "clampToEdge=" << document.getReplaceClampWithClampToEdge() << std::endl; document.setKeepExternalReferences((options->getOptionString().find("keepExternalReferences")!=std::string::npos)); - osg::notify(osg::DEBUG_INFO) << readerMsg << "keepExternalReferences=" << document.getKeepExternalReferences() << std::endl; + OSG_DEBUG << readerMsg << "keepExternalReferences=" << document.getKeepExternalReferences() << std::endl; document.setPreserveFace((options->getOptionString().find("preserveFace")!=std::string::npos)); - osg::notify(osg::DEBUG_INFO) << readerMsg << "preserveFace=" << document.getPreserveFace() << std::endl; + OSG_DEBUG << readerMsg << "preserveFace=" << document.getPreserveFace() << std::endl; document.setPreserveObject((options->getOptionString().find("preserveObject")!=std::string::npos)); - osg::notify(osg::DEBUG_INFO) << readerMsg << "preserveObject=" << document.getPreserveObject() << std::endl; + OSG_DEBUG << readerMsg << "preserveObject=" << document.getPreserveObject() << std::endl; + + document.setReplaceDoubleSidedPolys((options->getOptionString().find("replaceDoubleSidedPolys")!=std::string::npos)); + OSG_DEBUG << readerMsg << "replaceDoubleSidedPolys=" << document.getReplaceDoubleSidedPolys() << std::endl; document.setDefaultDOFAnimationState((options->getOptionString().find("dofAnimation")!=std::string::npos)); - osg::notify(osg::DEBUG_INFO) << readerMsg << "dofAnimation=" << document.getDefaultDOFAnimationState() << std::endl; + OSG_DEBUG << readerMsg << "dofAnimation=" << document.getDefaultDOFAnimationState() << std::endl; document.setUseBillboardCenter((options->getOptionString().find("billboardCenter")!=std::string::npos)); - osg::notify(osg::DEBUG_INFO) << readerMsg << "billboardCenter=" << document.getUseBillboardCenter() << std::endl; + OSG_DEBUG << readerMsg << "billboardCenter=" << document.getUseBillboardCenter() << std::endl; document.setUseTextureAlphaForTransparancyBinning(options->getOptionString().find("noTextureAlphaForTransparancyBinning")==std::string::npos); - osg::notify(osg::DEBUG_INFO) << readerMsg << "noTextureAlphaForTransparancyBinning=" << !document.getUseTextureAlphaForTransparancyBinning() << std::endl; + OSG_DEBUG << readerMsg << "noTextureAlphaForTransparancyBinning=" << !document.getUseTextureAlphaForTransparancyBinning() << std::endl; document.setReadObjectRecordData(options->getOptionString().find("readObjectRecordData")==std::string::npos); - osg::notify(osg::DEBUG_INFO) << readerMsg << "readObjectRecordData=" << !document.getReadObjectRecordData() << std::endl; + OSG_DEBUG << readerMsg << "readObjectRecordData=" << !document.getReadObjectRecordData() << std::endl; document.setDoUnitsConversion((options->getOptionString().find("noUnitsConversion")==std::string::npos)); // default to true, unless noUnitsConversion is specified. - osg::notify(osg::DEBUG_INFO) << readerMsg << "noUnitsConversion=" << !document.getDoUnitsConversion() << std::endl; + OSG_DEBUG << readerMsg << "noUnitsConversion=" << !document.getDoUnitsConversion() << std::endl; if (document.getDoUnitsConversion()) { @@ -533,9 +537,9 @@ class FLTReaderWriter : public ReaderWriter { if ( fileName.empty() ) { - osg::notify( osg::FATAL ) << "fltexp: writeNode: empty file name" << std::endl; return WriteResult::FILE_NOT_HANDLED; } + std::string ext = osgDB::getLowerCaseFileExtension( fileName ); if ( !acceptsExtension(ext) ) return WriteResult::FILE_NOT_HANDLED; @@ -549,7 +553,7 @@ class FLTReaderWriter : public ReaderWriter fOut.open( fileName.c_str(), std::ios::out | std::ios::binary ); if ( fOut.fail()) { - osg::notify( osg::FATAL ) << "fltexp: Failed to open output stream." << std::endl; + OSG_FATAL << "fltexp: Failed to open output stream." << std::endl; return WriteResult::ERROR_IN_WRITING_FILE; } @@ -583,7 +587,7 @@ class FLTReaderWriter : public ReaderWriter // If the temp directory doesn't already exist, make it. if ( !osgDB::makeDirectory( fltOpt->getTempDir() ) ) { - osg::notify( osg::FATAL ) << "fltexp: Error creating temp dir: " << fltOpt->getTempDir() << std::endl; + OSG_FATAL << "fltexp: Error creating temp dir: " << fltOpt->getTempDir() << std::endl; return WriteResult::ERROR_IN_WRITING_FILE; } } diff --git a/src/osgPlugins/OpenFlight/Record.h b/src/osgPlugins/OpenFlight/Record.h index 52cea77ac..64a835724 100644 --- a/src/osgPlugins/OpenFlight/Record.h +++ b/src/osgPlugins/OpenFlight/Record.h @@ -86,6 +86,7 @@ public: virtual void addVertex(Vertex& /*vertex*/) {} virtual void addVertexUV(int /*layer*/,const osg::Vec2& /*uv*/) {} virtual void addMorphVertex(Vertex& /*vertex0*/, Vertex& /*vertex100*/) {} + virtual void setMultiSwitchValueName(unsigned int /*switchSet*/, const std::string& /*name*/) {} void setNumberOfReplications(int num) { _numberOfReplications = num; } void setMatrix(const osg::Matrix& matrix) { _matrix = new osg::RefMatrix(matrix); } diff --git a/src/osgPlugins/OpenFlight/RecordInputStream.cpp b/src/osgPlugins/OpenFlight/RecordInputStream.cpp index 743dc7596..a5d904f17 100644 --- a/src/osgPlugins/OpenFlight/RecordInputStream.cpp +++ b/src/osgPlugins/OpenFlight/RecordInputStream.cpp @@ -47,7 +47,7 @@ bool RecordInputStream::readRecordBody(opcode_type opcode, size_type size, Docum const uint16 LITTLE_ENDIAN_POP_LEVEL_OP = 0x0B00; if (opcode==LITTLE_ENDIAN_POP_LEVEL_OP) { - osg::notify(osg::INFO) << "Little endian pop-level record" << std::endl; + OSG_INFO << "Little endian pop-level record" << std::endl; opcode=POP_LEVEL_OP; size=4; } @@ -76,7 +76,7 @@ bool RecordInputStream::readRecordBody(opcode_type opcode, size_type size, Docum } else // prototype not found { - osg::notify(osg::WARN) << "Unknown record, opcode=" << opcode << " size=" << size << std::endl; + OSG_WARN << "Unknown record, opcode=" << opcode << " size=" << size << std::endl; // Add to registry so we only have to see this error message once. Registry::instance()->addPrototype(opcode,new DummyRecord); diff --git a/src/osgPlugins/OpenFlight/Registry.cpp b/src/osgPlugins/OpenFlight/Registry.cpp index 3dd29f637..13bc72682 100644 --- a/src/osgPlugins/OpenFlight/Registry.cpp +++ b/src/osgPlugins/OpenFlight/Registry.cpp @@ -40,12 +40,12 @@ void Registry::addPrototype(int opcode, Record* prototype) { if (prototype==0L) { - osg::notify(osg::WARN) << "Not a record." << std::endl; + OSG_WARN << "Not a record." << std::endl; return; } if (_recordProtoMap.find(opcode) != _recordProtoMap.end()) - osg::notify(osg::WARN) << "Registry already contains prototype for opcode " << opcode << "." << std::endl; + OSG_WARN << "Registry already contains prototype for opcode " << opcode << "." << std::endl; _recordProtoMap[opcode] = prototype; } diff --git a/src/osgPlugins/OpenFlight/VertexPaletteManager.cpp b/src/osgPlugins/OpenFlight/VertexPaletteManager.cpp index 80593b7bb..ae6b8b47d 100644 --- a/src/osgPlugins/OpenFlight/VertexPaletteManager.cpp +++ b/src/osgPlugins/OpenFlight/VertexPaletteManager.cpp @@ -42,12 +42,12 @@ VertexPaletteManager::~VertexPaletteManager() // Delete our temp file. if (_verticesStr.is_open()) { - osg::notify( osg::WARN ) << "fltexp: VertexPaletteManager destructor has an open temp file." << std::endl; + OSG_WARN << "fltexp: VertexPaletteManager destructor has an open temp file." << std::endl; // This should not happen. FltExportVisitor::complete should close // this file before we get to this destructor. return; } - osg::notify( osg::INFO ) << "fltexp: Deleting temp file " << _verticesTempName << std::endl; + OSG_INFO << "fltexp: Deleting temp file " << _verticesTempName << std::endl; FLTEXP_DELETEFILE( _verticesTempName.c_str() ); } } @@ -58,7 +58,7 @@ VertexPaletteManager::add( const osg::Geometry& geom ) const osg::Array* v = geom.getVertexArray(); if (!v) { - osg::notify( osg::WARN ) << "fltexp: Attempting to add NULL vertex array in VertexPaletteManager." << std::endl; + OSG_WARN << "fltexp: Attempting to add NULL vertex array in VertexPaletteManager." << std::endl; return; } const osg::Array* c = geom.getColorArray(); @@ -129,12 +129,12 @@ VertexPaletteManager::byteOffset( unsigned int idx ) const { if (!_current) { - osg::notify( osg::WARN ) << "fltexp: No current vertex array in VertexPaletteManager." << std::endl; + OSG_WARN << "fltexp: No current vertex array in VertexPaletteManager." << std::endl; return 4; } if (idx >= _current->_idxCount) { - osg::notify( osg::WARN ) << "fltexp: Index out of range in VertexPaletteManager." << std::endl; + OSG_WARN << "fltexp: Index out of range in VertexPaletteManager." << std::endl; return 4; } @@ -232,19 +232,19 @@ VertexPaletteManager::writeRecords( const osg::Vec3dArray* v, const osg::Vec4Arr case VERTEX_CN: opcode = VERTEX_CN_OP; if (!n) - osg::notify( osg::WARN ) << "fltexp: VPM::writeRecords: no normal array." << std::endl; + OSG_WARN << "fltexp: VPM::writeRecords: no normal array." << std::endl; break; case VERTEX_CNT: opcode = VERTEX_CNT_OP; if (!n) - osg::notify( osg::WARN ) << "fltexp: VPM::writeRecords: no normal array." << std::endl; + OSG_WARN << "fltexp: VPM::writeRecords: no normal array." << std::endl; if (!t) - osg::notify( osg::WARN ) << "fltexp: VPM::writeRecords: no tex coord array." << std::endl; + OSG_WARN << "fltexp: VPM::writeRecords: no tex coord array." << std::endl; break; case VERTEX_CT: opcode = VERTEX_CT_OP; if (!t) - osg::notify( osg::WARN ) << "fltexp: VPM::writeRecords: no tex coord array." << std::endl; + OSG_WARN << "fltexp: VPM::writeRecords: no tex coord array." << std::endl; break; } @@ -368,7 +368,7 @@ VertexPaletteManager::asVec2Array( const osg::Array* in, const unsigned int n ) } default: { - osg::notify( osg::WARN ) << "fltexp: Unsupported array type in conversion to Vec2Array: " << arrayType << std::endl; + OSG_WARN << "fltexp: Unsupported array type in conversion to Vec2Array: " << arrayType << std::endl; return NULL; } } @@ -416,7 +416,7 @@ VertexPaletteManager::asVec3Array( const osg::Array* in, const unsigned int n ) } default: { - osg::notify( osg::WARN ) << "fltexp: Unsupported array type in conversion to Vec3Array: " << arrayType << std::endl; + OSG_WARN << "fltexp: Unsupported array type in conversion to Vec3Array: " << arrayType << std::endl; return NULL; } } @@ -464,7 +464,7 @@ VertexPaletteManager::asVec3dArray( const osg::Array* in, const unsigned int n ) } default: { - osg::notify( osg::WARN ) << "fltexp: Unsupported array type in conversion to Vec3dArray: " << arrayType << std::endl; + OSG_WARN << "fltexp: Unsupported array type in conversion to Vec3dArray: " << arrayType << std::endl; return NULL; } } @@ -520,7 +520,7 @@ VertexPaletteManager::asVec4Array( const osg::Array* in, const unsigned int n ) } default: { - osg::notify( osg::WARN ) << "fltexp: Unsupported array type in conversion to Vec4Array: " << arrayType << std::endl; + OSG_WARN << "fltexp: Unsupported array type in conversion to Vec4Array: " << arrayType << std::endl; return NULL; } } diff --git a/src/osgPlugins/OpenFlight/VertexRecords.cpp b/src/osgPlugins/OpenFlight/VertexRecords.cpp index 30c5cbb8f..a6de5eeff 100644 --- a/src/osgPlugins/OpenFlight/VertexRecords.cpp +++ b/src/osgPlugins/OpenFlight/VertexRecords.cpp @@ -190,17 +190,17 @@ class VertexCNT : public Record if (!coord.valid()) { - osg::notify(osg::NOTICE)<<"Warning: data error detected in VertexCNT::readRecord coord="<getWriteResult().warn( warning ); - osg::notify( osg::WARN ) << warning << std::endl; + OSG_WARN << warning << std::endl; continue; } uint16 length( (uint16)iLen ); @@ -100,7 +100,7 @@ FltExportVisitor::writeMatrix( const osg::Referenced* ref ) void FltExportVisitor::writeContinuationRecord( const unsigned short length ) { - osg::notify( osg::DEBUG_INFO ) << "fltexp: Continuation record length: " << length+4 << std::endl; + OSG_DEBUG << "fltexp: Continuation record length: " << length+4 << std::endl; _records->writeInt16( (int16) CONTINUATION_OP ); _records->writeUInt16( length+4 ); } diff --git a/src/osgPlugins/OpenFlight/expGeometryRecords.cpp b/src/osgPlugins/OpenFlight/expGeometryRecords.cpp index 2544a15b6..9eb500e31 100644 --- a/src/osgPlugins/OpenFlight/expGeometryRecords.cpp +++ b/src/osgPlugins/OpenFlight/expGeometryRecords.cpp @@ -185,7 +185,7 @@ FltExportVisitor::writeFace( const osg::Geode& geode, const osg::Geometry& geom, case GL_POINTS: { std::string warning( "fltexp: GL_POINTS not supported in FLT export." ); - osg::notify( osg::WARN ) << warning << std::endl; + OSG_WARN << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; break; @@ -195,7 +195,7 @@ FltExportVisitor::writeFace( const osg::Geode& geode, const osg::Geometry& geom, case GL_QUAD_STRIP: { std::string warning( "fltexp: Wrong mode in Face record." ); - osg::notify( osg::WARN ) << warning << std::endl; + OSG_WARN << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; break; @@ -248,7 +248,7 @@ FltExportVisitor::writeFace( const osg::Geode& geode, const osg::Geometry& geom, else { std::string warning( "fltexp: Face is textured, but Texture2D StateAttribute is NULL." ); - osg::notify( osg::WARN ) << warning << std::endl; + OSG_WARN << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); } } @@ -423,7 +423,7 @@ FltExportVisitor::writeMesh( const osg::Geode& geode, const osg::Geometry& geom else { std::string warning( "fltexp: Mesh is textured, but Texture2D StateAttribute is NULL." ); - osg::notify( osg::WARN ) << warning << std::endl; + OSG_WARN << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); } } @@ -579,7 +579,7 @@ FltExportVisitor::writeLocalVertexPool( const osg::Geometry& geom ) if (!v3) { std::string warning( "fltexp: writeLocalVertexPool: VertexArray is not Vec3Array." ); - osg::notify( osg::WARN ) << warning << std::endl; + OSG_WARN << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; } @@ -755,7 +755,7 @@ FltExportVisitor::writeMultitexture( const osg::Geometry& geom ) { std::ostringstream warning; warning << "fltexp: No Texture2D for unit " << idx; - osg::notify( osg::WARN ) << warning.str() << std::endl; + OSG_WARN << warning.str() << std::endl; _fltOpt->getWriteResult().warn( warning.str() ); } @@ -770,7 +770,7 @@ FltExportVisitor::writeMultitexture( const osg::Geometry& geom ) } void -FltExportVisitor::writeUVList( int numVerts, const osg::Geometry& geom ) +FltExportVisitor::writeUVList( int numVerts, const osg::Geometry& geom, const std::vector& indices ) { unsigned int numLayers( 0 ); uint32 flags( 0 ); @@ -794,32 +794,86 @@ FltExportVisitor::writeUVList( int numVerts, const osg::Geometry& geom ) osg::Vec2 defaultCoord( 0., 0. ); // const osg::StateSet* ss = getCurrentStateSet(); + for( int vertexIdx=0; vertexIdx( geom.getTexCoordArray( idx ) ); + osg::ref_ptr t2 = dynamic_cast( t ); + if (!t2.valid()) + { + std::ostringstream warning; + warning << "fltexp: No Texture2D for unit " << idx; + OSG_WARN << warning.str() << std::endl; + _fltOpt->getWriteResult().warn( warning.str() ); + t2 = new osg::Vec2Array; + } + + const int size = t2->getNumElements(); + int vIdx = indices[ vertexIdx ]; + osg::Vec2& tc( defaultCoord ); + if (vIdx < size) + tc = ( *t2 )[ vIdx ]; + _records->writeFloat32( tc[ 0 ] ); + _records->writeFloat32( tc[ 1 ] ); + } + } + } +} + + +void +FltExportVisitor::writeUVList( int numVerts, const osg::Geometry& geom, unsigned int first ) +{ + unsigned int numLayers( 0 ); + uint32 flags( 0 ); + unsigned int idx; for( idx=1; idx<8; idx++) { if( isTextured( idx, geom ) ) { - osg::Array* t = const_cast( geom.getTexCoordArray( idx ) ); - osg::ref_ptr t2 = dynamic_cast( t ); - if (!t2.valid()) - { - std::ostringstream warning; - warning << "fltexp: No Texture2D for unit " << idx; - osg::notify( osg::WARN ) << warning.str() << std::endl; - _fltOpt->getWriteResult().warn( warning.str() ); - t2 = new osg::Vec2Array; - } - else if (static_cast(t2->getNumElements()) != numVerts) - { - std::ostringstream warning; - warning << "fltexp: Invalid number of texture coordinates for unit " << idx; - osg::notify( osg::WARN ) << warning.str() << std::endl; - _fltOpt->getWriteResult().warn( warning.str() ); - } + flags |= LAYER_1 >> (idx-1); + numLayers++; + } + } + if( numLayers == 0 ) + return; - const int size = t2->getNumElements(); - int vIdx; - for( vIdx=0; vIdxwriteInt16( (int16) UV_LIST_OP ); + _records->writeUInt16( length ); + _records->writeInt32( flags ); + + osg::Vec2 defaultCoord( 0., 0. ); + for( int vertexIdx=0; vertexIdx( geom.getTexCoordArray( idx ) ); + osg::ref_ptr t2 = dynamic_cast( t ); + if (!t2.valid()) + { + std::ostringstream warning; + warning << "fltexp: No Texture2D for unit " << idx; + osg::notify( osg::WARN ) << warning.str() << std::endl; + _fltOpt->getWriteResult().warn( warning.str() ); + t2 = new osg::Vec2Array; + } + else if (t2->getNumElements() < first + numVerts) + { + std::ostringstream warning; + warning << "fltexp: Invalid number of texture coordinates for unit " << idx; + OSG_WARN << warning.str() << std::endl; + _fltOpt->getWriteResult().warn( warning.str() ); + } + + const int size = t2->getNumElements(); + int vIdx = first + vertexIdx; osg::Vec2& tc( defaultCoord ); if (vIdx < size) tc = (*t2)[ vIdx ]; @@ -1058,7 +1112,7 @@ FltExportVisitor::handleDrawElements( const osg::DrawElements* de, const osg::Ge int numVerts = writeVertexList( indices, n ); first += n; - writeUVList( numVerts, geom ); + writeUVList( numVerts, geom, indices ); writePop(); } diff --git a/src/osgPlugins/OpenFlight/expPrimaryRecords.cpp b/src/osgPlugins/OpenFlight/expPrimaryRecords.cpp index 2d5154194..9b6dd61b6 100644 --- a/src/osgPlugins/OpenFlight/expPrimaryRecords.cpp +++ b/src/osgPlugins/OpenFlight/expPrimaryRecords.cpp @@ -31,6 +31,7 @@ #include #include +#include // FIXME: This header was copied verbatim from the importer, with the only change // being that the symbols it defines are placed in namespace 'fltexp' instead @@ -282,7 +283,7 @@ FltExportVisitor::writeObject( const osg::Group& group, osgSim::ObjectRecordData if (!ord) { std::string warning( "fltexp: writeObject has invalid ObjectRecordData." ); - osg::notify( osg::WARN ) << warning << std::endl; + OSG_WARN << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; } diff --git a/src/osgSim/MultiSwitch.cpp b/src/osgSim/MultiSwitch.cpp index 6a74644e6..3fc8ddd62 100644 --- a/src/osgSim/MultiSwitch.cpp +++ b/src/osgSim/MultiSwitch.cpp @@ -163,6 +163,7 @@ void MultiSwitch::expandToEncompassSwitchSet(unsigned int switchSet) // need to expand arrays. unsigned int originalSize = _values.size(); _values.resize(switchSet+1); + _valueNames.resize(switchSet+1); for(unsigned int i=originalSize;i<=switchSet;++i) { ValueList& values = _values[i]; @@ -232,3 +233,10 @@ void MultiSwitch::setValueList(unsigned int switchSet, const ValueList& values) _values[switchSet] = values; } + +void MultiSwitch::setValueName(unsigned int switchSet, const std::string& name) +{ + expandToEncompassSwitchSet(switchSet); + + _valueNames[switchSet] = name; +}