| [7748] | 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| [5038] | 14 | |
|---|
| [7748] | 15 | |
|---|
| [5038] | 16 | |
|---|
| [7669] | 17 | |
|---|
| [5038] | 18 | |
|---|
| 19 | |
|---|
| 20 | #include <stdexcept> |
|---|
| 21 | #include <osg/Notify> |
|---|
| [5136] | 22 | #include <osg/ProxyNode> |
|---|
| [5038] | 23 | #include <osgDB/FileNameUtils> |
|---|
| 24 | #include <osgDB/FileUtils> |
|---|
| 25 | #include <osgDB/Registry> |
|---|
| 26 | #include <osgDB/ReadFile> |
|---|
| [6267] | 27 | #include <OpenThreads/ReentrantMutex> |
|---|
| [5218] | 28 | #include <osgUtil/Optimizer> |
|---|
| [5038] | 29 | |
|---|
| 30 | #include "Registry.h" |
|---|
| 31 | #include "Document.h" |
|---|
| 32 | #include "RecordInputStream.h" |
|---|
| [8003] | 33 | #include "DataOutputStream.h" |
|---|
| 34 | #include "FltExportVisitor.h" |
|---|
| 35 | #include "ExportOptions.h" |
|---|
| [5038] | 36 | |
|---|
| [6267] | 37 | #define SERIALIZER() OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_serializerMutex) |
|---|
| [5038] | 38 | |
|---|
| 39 | using namespace flt; |
|---|
| 40 | using namespace osg; |
|---|
| 41 | using namespace osgDB; |
|---|
| 42 | |
|---|
| [10283] | 43 | |
|---|
| 44 | USE_OSGPLUGIN(attr) |
|---|
| [5038] | 45 | |
|---|
| [10283] | 46 | |
|---|
| 47 | |
|---|
| 48 | |
|---|
| 49 | USE_FLTRECORD(Comment, COMMENT_OP) |
|---|
| 50 | USE_FLTRECORD(LongID, LONG_ID_OP) |
|---|
| 51 | USE_FLTRECORD(Matrix, MATRIX_OP) |
|---|
| 52 | USE_FLTRECORD(Multitexture, MULTITEXTURE_OP) |
|---|
| 53 | USE_FLTRECORD(UVList, UV_LIST_OP) |
|---|
| 54 | USE_FLTRECORD(Replicate, REPLICATE_OP) |
|---|
| 55 | USE_FLTRECORD(DummyRecord, OLD_TRANSLATE2_OP) |
|---|
| 56 | USE_FLTRECORD(DummyRecord, OLD_ROTATE_ABOUT_POINT_OP) |
|---|
| 57 | USE_FLTRECORD(DummyRecord, OLD_ROTATE_ABOUT_EDGE_OP) |
|---|
| 58 | USE_FLTRECORD(DummyRecord, OLD_SCALE_OP) |
|---|
| 59 | USE_FLTRECORD(DummyRecord, OLD_TRANSLATE_OP) |
|---|
| 60 | USE_FLTRECORD(DummyRecord, OLD_NONUNIFORM_SCALE_OP) |
|---|
| 61 | USE_FLTRECORD(DummyRecord, OLD_ROTATE_ABOUT_POINT2_OP) |
|---|
| 62 | USE_FLTRECORD(DummyRecord, OLD_ROTATE_SCALE_TO_POINT_OP) |
|---|
| 63 | USE_FLTRECORD(DummyRecord, OLD_PUT_TRANSFORM_OP) |
|---|
| 64 | USE_FLTRECORD(DummyRecord, OLD_BOUNDING_BOX_OP) |
|---|
| 65 | USE_FLTRECORD(DummyRecord, INDEXED_STRING_OP) |
|---|
| 66 | USE_FLTRECORD(DummyRecord, ROAD_ZONE_OP) |
|---|
| 67 | USE_FLTRECORD(DummyRecord, ROTATE_ABOUT_EDGE_OP) |
|---|
| 68 | USE_FLTRECORD(DummyRecord, TRANSLATE_OP) |
|---|
| 69 | USE_FLTRECORD(DummyRecord, NONUNIFORM_SCALE_OP) |
|---|
| 70 | USE_FLTRECORD(DummyRecord, ROTATE_ABOUT_POINT_OP) |
|---|
| 71 | USE_FLTRECORD(DummyRecord, ROTATE_SCALE_TO_POINT_OP) |
|---|
| 72 | USE_FLTRECORD(DummyRecord, PUT_TRANSFORM_OP) |
|---|
| 73 | USE_FLTRECORD(DummyRecord, GENERAL_MATRIX_OP) |
|---|
| 74 | USE_FLTRECORD(DummyRecord, VECTOR_OP) |
|---|
| 75 | USE_FLTRECORD(DummyRecord, BOUNDING_BOX_OP) |
|---|
| 76 | USE_FLTRECORD(DummyRecord, BOUNDING_SPHERE_OP) |
|---|
| 77 | USE_FLTRECORD(DummyRecord, BOUNDING_CYLINDER_OP) |
|---|
| 78 | USE_FLTRECORD(DummyRecord, BOUNDING_CONVEX_HULL_OP) |
|---|
| 79 | USE_FLTRECORD(DummyRecord, BOUNDING_HISTOGRAM) |
|---|
| 80 | USE_FLTRECORD(DummyRecord, BOUNDING_VOLUME_CENTER_OP) |
|---|
| 81 | USE_FLTRECORD(DummyRecord, BOUNDING_VOLUME_ORIENTATION_OP) |
|---|
| 82 | USE_FLTRECORD(DummyRecord, HISTOGRAM_BOUNDING_VOLUME_OP) |
|---|
| 83 | USE_FLTRECORD(PushLevel, PUSH_LEVEL_OP) |
|---|
| 84 | USE_FLTRECORD(PopLevel, POP_LEVEL_OP) |
|---|
| 85 | USE_FLTRECORD(PushSubface, PUSH_SUBFACE_OP) |
|---|
| 86 | USE_FLTRECORD(PopSubface, POP_SUBFACE_OP) |
|---|
| 87 | USE_FLTRECORD(PushExtension, PUSH_EXTENSION_OP) |
|---|
| 88 | USE_FLTRECORD(PopExtension, POP_EXTENSION_OP) |
|---|
| 89 | USE_FLTRECORD(PushAttribute, PUSH_ATTRIBUTE_OP) |
|---|
| 90 | USE_FLTRECORD(PopAttribute, POP_ATTRIBUTE_OP) |
|---|
| 91 | USE_FLTRECORD(Face, FACE_OP) |
|---|
| 92 | USE_FLTRECORD(VertexListRecord, VERTEX_LIST_OP) |
|---|
| 93 | USE_FLTRECORD(MorphVertexList, MORPH_VERTEX_LIST_OP) |
|---|
| 94 | USE_FLTRECORD(Mesh, MESH_OP) |
|---|
| 95 | USE_FLTRECORD(LocalVertexPool, LOCAL_VERTEX_POOL_OP) |
|---|
| 96 | USE_FLTRECORD(MeshPrimitive, MESH_PRIMITIVE_OP) |
|---|
| 97 | USE_FLTRECORD(LightPoint, LIGHT_POINT_OP) |
|---|
| 98 | USE_FLTRECORD(IndexedLightPoint, INDEXED_LIGHT_POINT_OP) |
|---|
| 99 | USE_FLTRECORD(LightPointSystem, LIGHT_POINT_SYSTEM_OP) |
|---|
| 100 | USE_FLTRECORD(VertexPalette, VERTEX_PALETTE_OP) |
|---|
| 101 | USE_FLTRECORD(ColorPalette, COLOR_PALETTE_OP) |
|---|
| 102 | USE_FLTRECORD(NameTable, NAME_TABLE_OP) |
|---|
| 103 | USE_FLTRECORD(MaterialPalette, MATERIAL_PALETTE_OP) |
|---|
| 104 | USE_FLTRECORD(OldMaterialPalette, OLD_MATERIAL_PALETTE_OP) |
|---|
| 105 | USE_FLTRECORD(TexturePalette, TEXTURE_PALETTE_OP) |
|---|
| 106 | USE_FLTRECORD(EyepointAndTrackplanePalette, EYEPOINT_AND_TRACKPLANE_PALETTE_OP) |
|---|
| 107 | USE_FLTRECORD(LinkagePalette, LINKAGE_PALETTE_OP) |
|---|
| 108 | USE_FLTRECORD(SoundPalette, SOUND_PALETTE_OP) |
|---|
| 109 | USE_FLTRECORD(LightSourcePalette, LIGHT_SOURCE_PALETTE_OP) |
|---|
| 110 | USE_FLTRECORD(LightPointAppearancePalette, LIGHT_POINT_APPEARANCE_PALETTE_OP) |
|---|
| 111 | USE_FLTRECORD(LightPointAnimationPalette, LIGHT_POINT_ANIMATION_PALETTE_OP) |
|---|
| 112 | USE_FLTRECORD(LineStylePalette, LINE_STYLE_PALETTE_OP) |
|---|
| 113 | USE_FLTRECORD(TextureMappingPalette, TEXTURE_MAPPING_PALETTE_OP) |
|---|
| 114 | USE_FLTRECORD(ShaderPalette, SHADER_PALETTE_OP) |
|---|
| 115 | USE_FLTRECORD(Header, HEADER_OP) |
|---|
| 116 | USE_FLTRECORD(Group, GROUP_OP) |
|---|
| 117 | USE_FLTRECORD(DegreeOfFreedom, DOF_OP) |
|---|
| 118 | USE_FLTRECORD(LevelOfDetail, LOD_OP) |
|---|
| 119 | USE_FLTRECORD(OldLevelOfDetail, OLD_LOD_OP) |
|---|
| 120 | USE_FLTRECORD(Switch, SWITCH_OP) |
|---|
| 121 | USE_FLTRECORD(ExternalReference, EXTERNAL_REFERENCE_OP) |
|---|
| 122 | USE_FLTRECORD(InstanceDefinition, INSTANCE_DEFINITION_OP) |
|---|
| 123 | USE_FLTRECORD(InstanceReference, INSTANCE_REFERENCE_OP) |
|---|
| 124 | USE_FLTRECORD(Extension, EXTENSION_OP) |
|---|
| 125 | USE_FLTRECORD(Object, OBJECT_OP) |
|---|
| 126 | USE_FLTRECORD(LightSource, LIGHT_SOURCE_OP) |
|---|
| 127 | USE_FLTRECORD(DummyRecord, 103) |
|---|
| 128 | USE_FLTRECORD(DummyRecord, 104) |
|---|
| 129 | USE_FLTRECORD(DummyRecord, 117) |
|---|
| 130 | USE_FLTRECORD(DummyRecord, 118) |
|---|
| 131 | USE_FLTRECORD(DummyRecord, 120) |
|---|
| 132 | USE_FLTRECORD(DummyRecord, 121) |
|---|
| 133 | USE_FLTRECORD(DummyRecord, 124) |
|---|
| 134 | USE_FLTRECORD(DummyRecord, 125) |
|---|
| 135 | USE_FLTRECORD(RoadSegment, ROAD_SEGMENT_OP) |
|---|
| 136 | USE_FLTRECORD(RoadConstruction, ROAD_CONSTRUCTION_OP) |
|---|
| 137 | USE_FLTRECORD(RoadPath, ROAD_PATH_OP) |
|---|
| 138 | USE_FLTRECORD(VertexC, VERTEX_C_OP) |
|---|
| 139 | USE_FLTRECORD(VertexCN, VERTEX_CN_OP) |
|---|
| 140 | USE_FLTRECORD(VertexCT, VERTEX_CT_OP) |
|---|
| 141 | USE_FLTRECORD(VertexCNT, VERTEX_CNT_OP) |
|---|
| 142 | USE_FLTRECORD(AbsoluteVertex, OLD_ABSOLUTE_VERTEX_OP) |
|---|
| 143 | USE_FLTRECORD(ShadedVertex, OLD_SHADED_VERTEX_OP) |
|---|
| 144 | USE_FLTRECORD(NormalVertex, OLD_NORMAL_VERTEX_OP) |
|---|
| 145 | |
|---|
| 146 | |
|---|
| 147 | |
|---|
| [5136] | 148 | class ReadExternalsVisitor : public osg::NodeVisitor |
|---|
| 149 | { |
|---|
| [5886] | 150 | osg::ref_ptr<ReaderWriter::Options> _options; |
|---|
| [5820] | 151 | bool _cloneExternalReferences; |
|---|
| [5136] | 152 | |
|---|
| 153 | public: |
|---|
| 154 | |
|---|
| 155 | ReadExternalsVisitor(ReaderWriter::Options* options) : |
|---|
| 156 | osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), |
|---|
| [5820] | 157 | _options(options), |
|---|
| 158 | _cloneExternalReferences(false) |
|---|
| [5136] | 159 | { |
|---|
| [5820] | 160 | if (options) |
|---|
| 161 | _cloneExternalReferences = (options->getOptionString().find("cloneExternalReferences")!=std::string::npos); |
|---|
| [5136] | 162 | } |
|---|
| [5820] | 163 | |
|---|
| [5136] | 164 | virtual ~ReadExternalsVisitor() {} |
|---|
| 165 | |
|---|
| 166 | virtual void apply(ProxyNode& node) |
|---|
| 167 | { |
|---|
| [5281] | 168 | |
|---|
| [5236] | 169 | _options->setUserData( node.getUserData() ); |
|---|
| [5281] | 170 | node.setUserData(NULL); |
|---|
| [5236] | 171 | |
|---|
| [5136] | 172 | for (unsigned int pos=0; pos<node.getNumFileNames(); pos++) |
|---|
| 173 | { |
|---|
| 174 | std::string filename = node.getFileName(pos); |
|---|
| 175 | |
|---|
| 176 | |
|---|
| [5820] | 177 | osg::ref_ptr<osg::Node> external = osgDB::readNodeFile(filename,_options.get()); |
|---|
| 178 | if (external.valid()) |
|---|
| 179 | { |
|---|
| 180 | if (_cloneExternalReferences) |
|---|
| 181 | external = dynamic_cast<osg::Node*>(external->clone(osg::CopyOp(osg::CopyOp::DEEP_COPY_NODES))); |
|---|
| 182 | |
|---|
| 183 | node.addChild(external.get()); |
|---|
| 184 | } |
|---|
| [5136] | 185 | } |
|---|
| 186 | } |
|---|
| 187 | }; |
|---|
| 188 | |
|---|
| 189 | |
|---|
| [5820] | 190 | |
|---|
| [8003] | 191 | |
|---|
| 192 | |
|---|
| [8564] | 193 | |
|---|
| [8003] | 194 | |
|---|
| 195 | |
|---|
| 196 | |
|---|
| 197 | |
|---|
| 198 | |
|---|
| 199 | |
|---|
| 200 | |
|---|
| 201 | |
|---|
| 202 | |
|---|
| 203 | |
|---|
| 204 | |
|---|
| 205 | |
|---|
| 206 | |
|---|
| 207 | |
|---|
| 208 | |
|---|
| 209 | |
|---|
| 210 | |
|---|
| 211 | |
|---|
| 212 | |
|---|
| 213 | |
|---|
| 214 | |
|---|
| 215 | |
|---|
| 216 | |
|---|
| 217 | |
|---|
| 218 | |
|---|
| 219 | |
|---|
| 220 | |
|---|
| 221 | |
|---|
| [5038] | 222 | class FLTReaderWriter : public ReaderWriter |
|---|
| 223 | { |
|---|
| 224 | public: |
|---|
| [8003] | 225 | FLTReaderWriter() |
|---|
| 226 | : _implicitPath( "." ) |
|---|
| [8578] | 227 | { |
|---|
| 228 | supportsExtension("flt","OpenFlight format"); |
|---|
| 229 | |
|---|
| [8596] | 230 | supportsOption("clampToEdge","Import option"); |
|---|
| 231 | supportsOption("keepExternalReferences","Import option"); |
|---|
| 232 | supportsOption("preserveFace","Import option"); |
|---|
| 233 | supportsOption("preserveObject","Import option"); |
|---|
| 234 | supportsOption("dofAnimation","Import option"); |
|---|
| 235 | supportsOption("billboardCenter","Import option"); |
|---|
| 236 | supportsOption("noTextureAlphaForTransparancyBinning","Import option"); |
|---|
| 237 | supportsOption("readObjectRecordData","Import option"); |
|---|
| 238 | supportsOption("noUnitsConversion","Import option"); |
|---|
| 239 | supportsOption("convertToFeet","Import option"); |
|---|
| 240 | supportsOption("convertToInches","Import option"); |
|---|
| 241 | supportsOption("convertToMeters","Import option"); |
|---|
| 242 | supportsOption("convertToKilometers","Import option"); |
|---|
| 243 | supportsOption("convertToNauticalMiles","Import option"); |
|---|
| [8595] | 244 | |
|---|
| [8596] | 245 | supportsOption( "version=<ver>", "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\"." ); |
|---|
| 246 | supportsOption( "units=<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\"." ); |
|---|
| 247 | 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." ); |
|---|
| 248 | supportsOption( "tempDir=<dir>", "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\"." ); |
|---|
| 249 | supportsOption( "lighting=<ON|OFF>", "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\"." ); |
|---|
| 250 | supportsOption( "stripTextureFilePath", "Export option: If present in the Options string, the exporter strips the path from texture file names, and writes only the texture file name to the FLT Texture Palette. By default, the exporter doesn't strip the path, and the name written to the Texture Palette is taken directly from the osg::Image object referenced by the osg::Texture2D StateAttribute." ); |
|---|
| [8578] | 251 | } |
|---|
| [8003] | 252 | |
|---|
| [5038] | 253 | virtual const char* className() const { return "FLT Reader/Writer"; } |
|---|
| 254 | |
|---|
| 255 | virtual bool acceptsExtension(const std::string& extension) const |
|---|
| 256 | { |
|---|
| [7169] | 257 | return equalCaseInsensitive(extension,"flt") || extension.empty(); |
|---|
| [5038] | 258 | } |
|---|
| 259 | |
|---|
| 260 | virtual ReadResult readObject(const std::string& file, const Options* options) const |
|---|
| 261 | { |
|---|
| 262 | return readNode(file, options); |
|---|
| 263 | } |
|---|
| 264 | |
|---|
| 265 | virtual ReadResult readNode(const std::string& file, const Options* options) const |
|---|
| 266 | { |
|---|
| 267 | SERIALIZER(); |
|---|
| 268 | |
|---|
| 269 | std::string ext = osgDB::getLowerCaseFileExtension(file); |
|---|
| 270 | if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; |
|---|
| 271 | |
|---|
| [5136] | 272 | std::string fileName = osgDB::findDataFile(file, options); |
|---|
| [5038] | 273 | if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; |
|---|
| 274 | |
|---|
| [5136] | 275 | |
|---|
| 276 | { |
|---|
| [5986] | 277 | osg::Node* node = flt::Registry::instance()->getExternalFromLocalCache(fileName); |
|---|
| [5136] | 278 | if (node) |
|---|
| 279 | return ReadResult(node, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE); |
|---|
| 280 | } |
|---|
| 281 | |
|---|
| 282 | |
|---|
| [5038] | 283 | osg::ref_ptr<Options> local_opt = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; |
|---|
| [11159] | 284 | local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName)); |
|---|
| [5122] | 285 | |
|---|
| [5136] | 286 | ReadResult rr; |
|---|
| [5122] | 287 | |
|---|
| [5136] | 288 | |
|---|
| 289 | { |
|---|
| [9124] | 290 | osgDB::ifstream istream; |
|---|
| [5136] | 291 | istream.imbue(std::locale::classic()); |
|---|
| 292 | istream.open(fileName.c_str(), std::ios::in | std::ios::binary); |
|---|
| 293 | |
|---|
| 294 | if (istream) |
|---|
| 295 | { |
|---|
| 296 | rr = readNode(istream,local_opt.get()); |
|---|
| 297 | } |
|---|
| 298 | } |
|---|
| 299 | |
|---|
| 300 | static int nestedExternalsLevel = 0; |
|---|
| 301 | if (rr.success()) |
|---|
| 302 | { |
|---|
| 303 | |
|---|
| [5986] | 304 | flt::Registry::instance()->addExternalToLocalCache(fileName,rr.getNode()); |
|---|
| [5461] | 305 | |
|---|
| 306 | bool keepExternalReferences = false; |
|---|
| 307 | if (options) |
|---|
| 308 | keepExternalReferences = (options->getOptionString().find("keepExternalReferences")!=std::string::npos); |
|---|
| [5136] | 309 | |
|---|
| [5461] | 310 | |
|---|
| 311 | if ( !keepExternalReferences ) |
|---|
| [5136] | 312 | { |
|---|
| [5461] | 313 | osg::notify(osg::DEBUG_INFO) << "keepExternalReferences not found, so externals will be re-readed"<<std::endl; |
|---|
| 314 | |
|---|
| 315 | if (rr.getNode()) |
|---|
| 316 | { |
|---|
| 317 | nestedExternalsLevel++; |
|---|
| 318 | ReadExternalsVisitor visitor(local_opt.get()); |
|---|
| 319 | rr.getNode()->accept(visitor); |
|---|
| 320 | nestedExternalsLevel--; |
|---|
| 321 | } |
|---|
| [5136] | 322 | } |
|---|
| [5461] | 323 | else |
|---|
| 324 | { |
|---|
| 325 | osg::notify(osg::DEBUG_INFO) << "keepExternalReferences found, so externals will be left as ProxyNodes"<<std::endl; |
|---|
| 326 | } |
|---|
| [5136] | 327 | } |
|---|
| 328 | |
|---|
| 329 | |
|---|
| 330 | if (nestedExternalsLevel==0) |
|---|
| 331 | flt::Registry::instance()->clearLocalCache(); |
|---|
| 332 | |
|---|
| 333 | return rr; |
|---|
| [5038] | 334 | } |
|---|
| 335 | |
|---|
| 336 | virtual ReadResult readObject(std::istream& fin, const Options* options) const |
|---|
| 337 | { |
|---|
| 338 | return readNode(fin, options); |
|---|
| 339 | } |
|---|
| 340 | |
|---|
| 341 | virtual ReadResult readNode(std::istream& fin, const Options* options) const |
|---|
| 342 | { |
|---|
| [5136] | 343 | Document document; |
|---|
| 344 | document.setOptions(options); |
|---|
| 345 | |
|---|
| [5236] | 346 | |
|---|
| [5136] | 347 | if (options) |
|---|
| [5038] | 348 | { |
|---|
| [5205] | 349 | const char readerMsg[] = "flt reader option: "; |
|---|
| [5461] | 350 | |
|---|
| [5794] | 351 | document.setReplaceClampWithClampToEdge((options->getOptionString().find("clampToEdge")!=std::string::npos)); |
|---|
| 352 | osg::notify(osg::DEBUG_INFO) << readerMsg << "clampToEdge=" << document.getReplaceClampWithClampToEdge() << std::endl; |
|---|
| 353 | |
|---|
| [5461] | 354 | document.setKeepExternalReferences((options->getOptionString().find("keepExternalReferences")!=std::string::npos)); |
|---|
| 355 | osg::notify(osg::DEBUG_INFO) << readerMsg << "keepExternalReferences=" << document.getKeepExternalReferences() << std::endl; |
|---|
| [5205] | 356 | |
|---|
| [5238] | 357 | document.setPreserveFace((options->getOptionString().find("preserveFace")!=std::string::npos)); |
|---|
| 358 | osg::notify(osg::DEBUG_INFO) << readerMsg << "preserveFace=" << document.getPreserveFace() << std::endl; |
|---|
| [5205] | 359 | |
|---|
| [5528] | 360 | document.setPreserveObject((options->getOptionString().find("preserveObject")!=std::string::npos)); |
|---|
| 361 | osg::notify(osg::DEBUG_INFO) << readerMsg << "preserveObject=" << document.getPreserveObject() << std::endl; |
|---|
| 362 | |
|---|
| [5205] | 363 | document.setDefaultDOFAnimationState((options->getOptionString().find("dofAnimation")!=std::string::npos)); |
|---|
| 364 | osg::notify(osg::DEBUG_INFO) << readerMsg << "dofAnimation=" << document.getDefaultDOFAnimationState() << std::endl; |
|---|
| 365 | |
|---|
| [5610] | 366 | document.setUseBillboardCenter((options->getOptionString().find("billboardCenter")!=std::string::npos)); |
|---|
| 367 | osg::notify(osg::DEBUG_INFO) << readerMsg << "billboardCenter=" << document.getUseBillboardCenter() << std::endl; |
|---|
| 368 | |
|---|
| [5136] | 369 | document.setUseTextureAlphaForTransparancyBinning(options->getOptionString().find("noTextureAlphaForTransparancyBinning")==std::string::npos); |
|---|
| [5610] | 370 | osg::notify(osg::DEBUG_INFO) << readerMsg << "noTextureAlphaForTransparancyBinning=" << !document.getUseTextureAlphaForTransparancyBinning() << std::endl; |
|---|
| [5038] | 371 | |
|---|
| [7931] | 372 | document.setReadObjectRecordData(options->getOptionString().find("readObjectRecordData")==std::string::npos); |
|---|
| 373 | osg::notify(osg::DEBUG_INFO) << readerMsg << "readObjectRecordData=" << !document.getReadObjectRecordData() << std::endl; |
|---|
| 374 | |
|---|
| [5205] | 375 | document.setDoUnitsConversion((options->getOptionString().find("noUnitsConversion")==std::string::npos)); |
|---|
| [5610] | 376 | osg::notify(osg::DEBUG_INFO) << readerMsg << "noUnitsConversion=" << !document.getDoUnitsConversion() << std::endl; |
|---|
| [5205] | 377 | |
|---|
| [5136] | 378 | if (document.getDoUnitsConversion()) |
|---|
| [5038] | 379 | { |
|---|
| [5136] | 380 | if (options->getOptionString().find("convertToFeet")!=std::string::npos) |
|---|
| 381 | document.setDesiredUnits(FEET); |
|---|
| 382 | else if (options->getOptionString().find("convertToInches")!=std::string::npos) |
|---|
| 383 | document.setDesiredUnits(INCHES); |
|---|
| 384 | else if (options->getOptionString().find("convertToMeters")!=std::string::npos) |
|---|
| 385 | document.setDesiredUnits(METERS); |
|---|
| 386 | else if (options->getOptionString().find("convertToKilometers")!=std::string::npos) |
|---|
| 387 | document.setDesiredUnits(KILOMETERS); |
|---|
| 388 | else if (options->getOptionString().find("convertToNauticalMiles")!=std::string::npos) |
|---|
| 389 | document.setDesiredUnits(NAUTICAL_MILES); |
|---|
| [5038] | 390 | } |
|---|
| [5236] | 391 | |
|---|
| 392 | const ParentPools* pools = dynamic_cast<const ParentPools*>( options->getUserData() ); |
|---|
| 393 | if (pools) |
|---|
| 394 | { |
|---|
| 395 | |
|---|
| 396 | |
|---|
| 397 | if (pools->getColorPool()) |
|---|
| 398 | document.setColorPool( pools->getColorPool(), true ); |
|---|
| 399 | if (pools->getTexturePool()) |
|---|
| 400 | document.setTexturePool( pools->getTexturePool(), true ); |
|---|
| 401 | if (pools->getMaterialPool()) |
|---|
| 402 | document.setMaterialPool( pools->getMaterialPool(), true ); |
|---|
| [6091] | 403 | if (pools->getLightSourcePool()) |
|---|
| 404 | document.setLightSourcePool( pools->getLightSourcePool(), true ); |
|---|
| [5236] | 405 | if (pools->getLPAppearancePool()) |
|---|
| 406 | document.setLightPointAppearancePool( pools->getLPAppearancePool(), true ); |
|---|
| [6759] | 407 | if (pools->getLPAnimationPool()) |
|---|
| 408 | document.setLightPointAnimationPool( pools->getLPAnimationPool(), true ); |
|---|
| [5236] | 409 | if (pools->getShaderPool()) |
|---|
| 410 | document.setShaderPool( pools->getShaderPool(), true ); |
|---|
| 411 | } |
|---|
| [5136] | 412 | } |
|---|
| [5038] | 413 | |
|---|
| [7669] | 414 | const int RECORD_HEADER_SIZE = 4; |
|---|
| [8564] | 415 | opcode_type continuationOpcode = INVALID_OP; |
|---|
| [7669] | 416 | std::string continuationBuffer; |
|---|
| 417 | |
|---|
| 418 | while (fin.good() && !document.done()) |
|---|
| [5136] | 419 | { |
|---|
| [7669] | 420 | |
|---|
| 421 | |
|---|
| 422 | |
|---|
| 423 | std::istream::pos_type pos = fin.tellg(); |
|---|
| 424 | |
|---|
| 425 | |
|---|
| 426 | flt::DataInputStream dataStream(fin.rdbuf()); |
|---|
| 427 | opcode_type opcode = (opcode_type)dataStream.readUInt16(); |
|---|
| 428 | size_type size = (size_type)dataStream.readUInt16(); |
|---|
| 429 | |
|---|
| [8564] | 430 | |
|---|
| 431 | |
|---|
| [8295] | 432 | if (size==0) |
|---|
| [8564] | 433 | { |
|---|
| 434 | |
|---|
| 435 | |
|---|
| 436 | if (document.getHeaderNode()) |
|---|
| 437 | { |
|---|
| 438 | return document.getHeaderNode(); |
|---|
| 439 | } |
|---|
| 440 | else |
|---|
| 441 | { |
|---|
| 442 | return ReadResult::ERROR_IN_READING_FILE; |
|---|
| 443 | } |
|---|
| 444 | } |
|---|
| [8295] | 445 | |
|---|
| [7669] | 446 | |
|---|
| 447 | if (!continuationBuffer.empty() && opcode!=CONTINUATION_OP) |
|---|
| [5038] | 448 | { |
|---|
| [7669] | 449 | |
|---|
| 450 | std::stringbuf sb(continuationBuffer); |
|---|
| 451 | flt::RecordInputStream recordStream(&sb); |
|---|
| 452 | recordStream.readRecordBody(continuationOpcode, continuationBuffer.length(), document); |
|---|
| 453 | |
|---|
| [8564] | 454 | continuationOpcode = INVALID_OP; |
|---|
| [7669] | 455 | continuationBuffer.clear(); |
|---|
| [5038] | 456 | } |
|---|
| [7669] | 457 | |
|---|
| 458 | |
|---|
| 459 | |
|---|
| 460 | if (opcode==EXTENSION_OP || |
|---|
| 461 | opcode==NAME_TABLE_OP || |
|---|
| 462 | opcode==LOCAL_VERTEX_POOL_OP || |
|---|
| 463 | opcode==MESH_PRIMITIVE_OP) |
|---|
| 464 | { |
|---|
| 465 | continuationOpcode = opcode; |
|---|
| 466 | |
|---|
| 467 | if (size > RECORD_HEADER_SIZE) |
|---|
| 468 | { |
|---|
| 469 | |
|---|
| 470 | std::string buffer((std::string::size_type)size-RECORD_HEADER_SIZE,'\0'); |
|---|
| 471 | fin.read(&buffer[0], size-RECORD_HEADER_SIZE); |
|---|
| 472 | |
|---|
| 473 | |
|---|
| 474 | continuationBuffer = buffer; |
|---|
| 475 | } |
|---|
| 476 | } |
|---|
| 477 | else if (opcode==CONTINUATION_OP) |
|---|
| 478 | { |
|---|
| 479 | if (size > RECORD_HEADER_SIZE) |
|---|
| 480 | { |
|---|
| 481 | std::string buffer((std::string::size_type)size-RECORD_HEADER_SIZE,'\0'); |
|---|
| 482 | fin.read(&buffer[0], size-RECORD_HEADER_SIZE); |
|---|
| 483 | |
|---|
| 484 | |
|---|
| 485 | continuationBuffer.append(buffer); |
|---|
| 486 | } |
|---|
| 487 | } |
|---|
| 488 | else if (opcode==VERTEX_PALETTE_OP) |
|---|
| 489 | { |
|---|
| 490 | |
|---|
| 491 | flt::RecordInputStream recordStream(fin.rdbuf()); |
|---|
| 492 | recordStream.readRecordBody(opcode, size, document); |
|---|
| 493 | } |
|---|
| 494 | else |
|---|
| 495 | { |
|---|
| 496 | |
|---|
| 497 | std::string buffer((std::string::size_type)size,'\0'); |
|---|
| 498 | if (size > RECORD_HEADER_SIZE) |
|---|
| 499 | fin.read(&buffer[0], size-RECORD_HEADER_SIZE); |
|---|
| 500 | |
|---|
| 501 | |
|---|
| 502 | std::stringbuf sb(buffer); |
|---|
| 503 | flt::RecordInputStream recordStream(&sb); |
|---|
| 504 | recordStream.readRecordBody(opcode, size, document); |
|---|
| 505 | } |
|---|
| [5136] | 506 | } |
|---|
| [5038] | 507 | |
|---|
| [5136] | 508 | if (!document.getHeaderNode()) |
|---|
| 509 | return ReadResult::ERROR_IN_READING_FILE; |
|---|
| [5461] | 510 | |
|---|
| [5218] | 511 | if (!document.getPreserveFace()) |
|---|
| 512 | { |
|---|
| 513 | osgUtil::Optimizer optimizer; |
|---|
| [6257] | 514 | optimizer.optimize(document.getHeaderNode(), |
|---|
| 515 | osgUtil::Optimizer::SHARE_DUPLICATE_STATE | |
|---|
| 516 | osgUtil::Optimizer::MERGE_GEOMETRY | |
|---|
| 517 | osgUtil::Optimizer::MERGE_GEODES | |
|---|
| 518 | osgUtil::Optimizer::TESSELLATE_GEOMETRY | |
|---|
| 519 | osgUtil::Optimizer::STATIC_OBJECT_DETECTION); |
|---|
| [5218] | 520 | } |
|---|
| [5038] | 521 | |
|---|
| [5136] | 522 | return document.getHeaderNode(); |
|---|
| [5038] | 523 | } |
|---|
| 524 | |
|---|
| 525 | virtual WriteResult writeObject(const Object& object,const std::string& fileName, const osgDB::ReaderWriter::Options* options) const |
|---|
| 526 | { |
|---|
| 527 | const Node* node = dynamic_cast<const Node*>(&object); |
|---|
| 528 | if (node) return writeNode( *node, fileName, options ); |
|---|
| 529 | return WriteResult::FILE_NOT_HANDLED; |
|---|
| 530 | } |
|---|
| 531 | |
|---|
| [8003] | 532 | virtual WriteResult writeNode( const osg::Node& node, const std::string& fileName, const Options* options ) const |
|---|
| [5038] | 533 | { |
|---|
| [8003] | 534 | if ( fileName.empty() ) |
|---|
| 535 | { |
|---|
| 536 | return WriteResult::FILE_NOT_HANDLED; |
|---|
| 537 | } |
|---|
| [9890] | 538 | |
|---|
| [8003] | 539 | std::string ext = osgDB::getLowerCaseFileExtension( fileName ); |
|---|
| 540 | if ( !acceptsExtension(ext) ) |
|---|
| 541 | return WriteResult::FILE_NOT_HANDLED; |
|---|
| 542 | |
|---|
| 543 | |
|---|
| 544 | std::string filePath = osgDB::getFilePath( fileName ); |
|---|
| 545 | if (!filePath.empty()) |
|---|
| 546 | _implicitPath = filePath; |
|---|
| 547 | |
|---|
| [9124] | 548 | osgDB::ofstream fOut; |
|---|
| [8003] | 549 | fOut.open( fileName.c_str(), std::ios::out | std::ios::binary ); |
|---|
| 550 | if ( fOut.fail()) |
|---|
| 551 | { |
|---|
| 552 | osg::notify( osg::FATAL ) << "fltexp: Failed to open output stream." << std::endl; |
|---|
| 553 | return WriteResult::ERROR_IN_WRITING_FILE; |
|---|
| 554 | } |
|---|
| 555 | |
|---|
| 556 | WriteResult wr = WriteResult::FILE_NOT_HANDLED; |
|---|
| 557 | wr = writeNode( node, fOut, options ); |
|---|
| 558 | fOut.close(); |
|---|
| 559 | |
|---|
| 560 | return wr; |
|---|
| [5038] | 561 | } |
|---|
| [8003] | 562 | |
|---|
| 563 | |
|---|
| [5038] | 564 | virtual WriteResult writeObject(const Object& object,std::ostream& fout, const osgDB::ReaderWriter::Options* options) const |
|---|
| 565 | { |
|---|
| 566 | const Node* node = dynamic_cast<const Node*>(&object); |
|---|
| 567 | if (node) return writeNode( *node, fout, options ); |
|---|
| 568 | return WriteResult::FILE_NOT_HANDLED; |
|---|
| 569 | } |
|---|
| 570 | |
|---|
| [8003] | 571 | virtual WriteResult writeNode( const osg::Node& node, std::ostream& fOut, const Options* options ) const |
|---|
| [5038] | 572 | { |
|---|
| [8003] | 573 | |
|---|
| 574 | ExportOptions* fltOpt = new ExportOptions( options ); |
|---|
| 575 | fltOpt->parseOptionsString(); |
|---|
| 576 | |
|---|
| 577 | |
|---|
| 578 | |
|---|
| 579 | if (fltOpt->getTempDir().empty()) |
|---|
| 580 | fltOpt->setTempDir( _implicitPath ); |
|---|
| 581 | if (!fltOpt->getTempDir().empty()) |
|---|
| 582 | { |
|---|
| 583 | |
|---|
| 584 | if ( !osgDB::makeDirectory( fltOpt->getTempDir() ) ) |
|---|
| 585 | { |
|---|
| 586 | osg::notify( osg::FATAL ) << "fltexp: Error creating temp dir: " << fltOpt->getTempDir() << std::endl; |
|---|
| 587 | return WriteResult::ERROR_IN_WRITING_FILE; |
|---|
| 588 | } |
|---|
| 589 | } |
|---|
| 590 | |
|---|
| 591 | flt::DataOutputStream dos( fOut.rdbuf(), fltOpt->getValidateOnly() ); |
|---|
| 592 | flt::FltExportVisitor fnv( &dos, fltOpt ); |
|---|
| 593 | |
|---|
| 594 | |
|---|
| 595 | |
|---|
| 596 | |
|---|
| 597 | osg::Node* nodeNonConst = const_cast<osg::Node*>( &node ); |
|---|
| [8010] | 598 | if (!nodeNonConst) |
|---|
| 599 | return WriteResult::ERROR_IN_WRITING_FILE; |
|---|
| [8003] | 600 | nodeNonConst->accept( fnv ); |
|---|
| 601 | fnv.complete( node ); |
|---|
| 602 | |
|---|
| [8010] | 603 | return fltOpt->getWriteResult(); |
|---|
| [5038] | 604 | } |
|---|
| 605 | |
|---|
| 606 | protected: |
|---|
| [8003] | 607 | mutable std::string _implicitPath; |
|---|
| [5038] | 608 | |
|---|
| [6267] | 609 | mutable OpenThreads::ReentrantMutex _serializerMutex; |
|---|
| [5038] | 610 | }; |
|---|
| 611 | |
|---|
| 612 | |
|---|
| 613 | |
|---|
| [7076] | 614 | REGISTER_OSGPLUGIN(OpenFlight, FLTReaderWriter) |
|---|