- Timestamp:
- 02/11/10 12:56:43 (3 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgPlugins/3ds/ReaderWriter3DS.cpp
r10942 r11056 1 #define ENABLE_3DS_WRITER 1 // Enables the 3DS writer (the define should be removed when the writer will be stable and tested enough)2 1 3 2 #include <osg/Notify> … … 21 20 #include <osg/NodeVisitor> 22 21 23 #ifdef ENABLE_3DS_WRITER 24 #include "WriterNodeVisitor.h" 25 #endif 22 #include "WriterNodeVisitor.h" 26 23 #include "lib3ds/lib3ds.h" 27 24 #include <stdlib.h> … … 172 169 virtual ReadResult readNode(const std::string& file, const osgDB::ReaderWriter::Options* options) const; 173 170 virtual ReadResult readNode(std::istream& fin, const Options* options) const; 174 #if ENABLE_3DS_WRITER 171 virtual ReadResult doReadNode(std::istream& fin, const Options* options, const std::string & fileNamelib3ds) const; ///< Subfunction of readNode()s functions. 172 175 173 virtual WriteResult writeNode(const osg::Node& /*node*/,const std::string& /*fileName*/,const Options* =NULL) const; 176 174 virtual WriteResult writeNode(const osg::Node& /*node*/,std::ostream& /*fout*/,const Options* =NULL) const; 177 #endif 175 virtual WriteResult doWriteNode(const osg::Node& /*node*/,std::ostream& /*fout*/,const Options*, const std::string & fileNamelib3ds) const; 178 176 179 177 protected: 180 178 ReadResult constructFrom3dsFile(Lib3dsFile *f,const std::string& filename, const Options* options) const; 181 179 182 #if ENABLE_3DS_WRITER183 180 bool createFileObject(const osg::Node& node, Lib3dsFile * file3ds,const std::string& fileName, const osgDB::ReaderWriter::Options* options) const; 184 #endif185 181 186 182 class ReaderObject … … 221 217 { 222 218 supportsExtension("3ds","3D Studio model format"); 223 supportsOption("OutputTextureFiles","Write out the texture images to file"); 219 //supportsOption("OutputTextureFiles","Write out the texture images to file"); 220 //supportsOption("flipTexture", "flip texture upside-down"); 221 supportsOption("extended3dsFilePaths", "Keeps long texture filenames (not 8.3) when exporting 3DS, but can lead to compatibility problems."); 222 supportsOption("noMatrixTransforms", "Set the plugin to apply matrices into the mesh vertices (\"old behaviour\") instead of restoring them (\"new behaviour\"). You may use this option to avoid a few rounding errors."); 223 supportsOption("checkForEspilonIdentityMatrices", "If not set, then consider \"almost identity\" matrices to be identity ones (in case of rounding errors)."); 224 supportsOption("restoreMatrixTransformsNoMeshes", "Makes an exception to the behaviour when 'noMatrixTransforms' is not set for mesh instances. When a mesh instance has a transform on it, the reader creates a MatrixTransform above the Geode. If you don't want the hierarchy to be modified, then you can use this option to merge the transform into vertices."); 224 225 setByteOrder(); 225 226 … … 253 254 restoreMatrixTransformsNoMeshes(false) 254 255 { 255 std::istringstream iss(options->getOptionString()); 256 std::string opt; 257 while (iss >> opt) 258 { 259 if (opt == "noMatrixTransforms") 260 noMatrixTransforms = true; 261 if (opt == "checkForEspilonIdentityMatrices") 262 checkForEspilonIdentityMatrices = true; 263 if (opt == "restoreMatrixTransformsNoMeshes") 264 restoreMatrixTransformsNoMeshes = true; 256 if (options) { 257 std::istringstream iss(options->getOptionString()); 258 std::string opt; 259 while (iss >> opt) 260 { 261 if (opt == "noMatrixTransforms") 262 noMatrixTransforms = true; 263 if (opt == "checkForEspilonIdentityMatrices") 264 checkForEspilonIdentityMatrices = true; 265 if (opt == "restoreMatrixTransformsNoMeshes") 266 restoreMatrixTransformsNoMeshes = true; 267 } 265 268 } 266 269 } … … 557 560 } 558 561 559 #if ENABLE_3DS_WRITER560 562 static long fileo_seek_func(void *self, long offset, Lib3dsIoSeek origin) { 561 563 std::ostream *f = reinterpret_cast<std::ostream*>(self); … … 567 569 return f->fail() ? -1 : 0; 568 570 } 569 #endif570 571 571 572 static long filei_tell_func(void *self) { … … 574 575 } 575 576 576 #if ENABLE_3DS_WRITER577 577 static long fileo_tell_func(void *self) { 578 578 std::ostream *f = reinterpret_cast<std::ostream*>(self); 579 579 return f->tellp(); 580 580 } 581 #endif582 581 583 582 … … 588 587 } 589 588 590 #if ENABLE_3DS_WRITER591 589 static size_t fileo_write_func(void *self, const void *buffer, size_t size) { 592 590 std::ostream *f = reinterpret_cast<std::ostream*>(self); … … 594 592 return f->fail() ? 0 : size; 595 593 } 596 #endif597 594 598 595 static void fileio_log_func(void *self, Lib3dsLogLevel level, int indent, const char *msg) 599 596 { 600 597 osg::NotifySeverity l = osg::INFO; 601 if (level == LIB3DS_LOG_ERROR) l = osg::FATAL; 602 else if (level == LIB3DS_LOG_WARN) l = osg::WARN; 598 // Intentionally NOT mapping 3DS levels with OSG levels 599 if (level == LIB3DS_LOG_ERROR) l = osg::WARN; 600 else if (level == LIB3DS_LOG_WARN) l = osg::NOTICE; 603 601 else if (level == LIB3DS_LOG_INFO) l = osg::INFO; 604 602 else if (level == LIB3DS_LOG_DEBUG) l = osg::DEBUG_INFO; … … 609 607 osgDB::ReaderWriter::ReadResult ReaderWriter3DS::readNode(std::istream& fin, const osgDB::ReaderWriter::Options* options) const 610 608 { 611 osgDB::ReaderWriter::ReadResult result = ReadResult::FILE_NOT_HANDLED; 612 613 std::string optFileName = ""; 609 std::string optFileName; 614 610 if (options) 615 611 { … … 617 613 if (optFileName.empty()) optFileName = options->getPluginStringData("filename"); 618 614 } 615 return doReadNode(fin, options, optFileName); 616 } 617 618 osgDB::ReaderWriter::ReadResult ReaderWriter3DS::doReadNode(std::istream& fin, const osgDB::ReaderWriter::Options* options, const std::string & fileNamelib3ds) const 619 { 620 osg::ref_ptr<Options> local_opt = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; 621 local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileNamelib3ds)); 622 623 osgDB::ReaderWriter::ReadResult result = ReadResult::FILE_NOT_HANDLED; 619 624 620 625 // Prepare io structure to tell how to read the stream … … 630 635 if (lib3ds_file_read(file3ds, &io) != 0) 631 636 { 632 result = constructFrom3dsFile(file3ds, optFileName,options);637 result = constructFrom3dsFile(file3ds,fileNamelib3ds,options); 633 638 lib3ds_file_free(file3ds); 634 639 } … … 639 644 osgDB::ReaderWriter::ReadResult ReaderWriter3DS::readNode(const std::string& file, const osgDB::ReaderWriter::Options* options) const 640 645 { 641 osgDB::ReaderWriter::ReadResult result = ReadResult::FILE_NOT_HANDLED;642 643 646 std::string ext = osgDB::getLowerCaseFileExtension(file); 644 647 if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; … … 647 650 if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; 648 651 649 Lib3dsFile *f = lib3ds_file_open(fileName.c_str() /*,options*/); 652 // Do not use the lib3ds_file_open() as: 653 // 1. It relies on FILE* instead of iostreams (less safe) 654 // 2. It doesn't allow us to set a custom log output 655 std::ifstream fin(file.c_str(), std::ios_base::in | std::ios_base::binary); 656 if (!fin.good()) return ReadResult::ERROR_IN_READING_FILE; 657 return doReadNode(fin, options, fileName); 658 /* 659 osgDB::ReaderWriter::ReadResult result = ReadResult::FILE_NOT_HANDLED; 660 Lib3dsFile *f = lib3ds_file_open(fileName.c_str()); // ,options 650 661 651 662 if (f) … … 659 670 660 671 return result; 672 */ 661 673 } 662 674 … … 1059 1071 1060 1072 1061 1062 #if ENABLE_3DS_WRITER1063 1073 osgDB::ReaderWriter::WriteResult ReaderWriter3DS::writeNode(const osg::Node& node,const std::string& fileName,const Options* options) const { 1064 1074 std::string ext = osgDB::getLowerCaseFileExtension(fileName); 1065 1075 if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; 1066 1076 1067 //osg::notify(osg::WARN) << "!!WARNING!! 3DS write support is incomplete" << std::endl; 1068 1077 osgDB::makeDirectoryForFile(fileName.c_str()); 1078 std::ofstream fout(fileName.c_str(), std::ios_base::out | std::ios_base::binary); 1079 if (!fout.good()) return WriteResult::ERROR_IN_WRITING_FILE; 1080 return doWriteNode(node, fout, options, fileName); 1081 /* 1069 1082 bool ok = true; 1070 1083 Lib3dsFile * file3ds = lib3ds_file_new(); … … 1075 1088 local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName)); 1076 1089 1077 if (!createFileObject(node, file3ds, fileName, local_opt .get())) ok = false;1090 if (!createFileObject(node, file3ds, fileName, local_opt)) ok = false; 1078 1091 if (ok && !lib3ds_file_save(file3ds, fileName.c_str())) ok = false; 1079 1092 } catch (...) { … … 1084 1097 1085 1098 return ok ? WriteResult(WriteResult::FILE_SAVED) : WriteResult(WriteResult::ERROR_IN_WRITING_FILE); 1086 //return ok ? WriteResult(WriteResult::FILE_SAVED) : WriteResult(WriteResult::FILE_NOT_HANDLED); 1099 */ 1087 1100 } 1088 1101 … … 1090 1103 osgDB::ReaderWriter::WriteResult ReaderWriter3DS::writeNode(const osg::Node& node,std::ostream& fout,const Options* options) const { 1091 1104 //osg::notify(osg::WARN) << "!!WARNING!! 3DS write support is incomplete" << std::endl; 1092 std::string optFileName = ""; 1093 if (options) 1094 { 1105 std::string optFileName; 1106 if (options) { 1095 1107 optFileName = options->getPluginStringData("STREAM_FILENAME"); 1096 1108 } 1109 1110 return doWriteNode(node, fout, options, optFileName); 1111 } 1112 1113 osgDB::ReaderWriter::WriteResult ReaderWriter3DS::doWriteNode(const osg::Node& node,std::ostream& fout, const Options* options, const std::string & fileNamelib3ds) const { 1114 osg::ref_ptr<Options> local_opt = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; 1115 local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileNamelib3ds)); 1097 1116 1098 1117 Lib3dsIo io; … … 1105 1124 1106 1125 Lib3dsFile * file3ds = lib3ds_file_new(); 1126 if (!file3ds) return WriteResult(WriteResult::ERROR_IN_WRITING_FILE); 1127 1107 1128 bool ok = true; 1108 1129 try { 1109 osg::ref_ptr<Options> local_opt = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; 1110 local_opt->getDatabasePathList().push_front(osgDB::getFilePath(optFileName)); 1111 1112 if (!createFileObject(node, file3ds, optFileName, local_opt.get())) ok = false; 1130 if (!createFileObject(node, file3ds, fileNamelib3ds, local_opt.get())) ok = false; 1113 1131 if (ok && !lib3ds_file_write(file3ds, &io)) ok = false; 1114 1132 … … 1123 1141 } 1124 1142 1125 const std::string getParent(const std::string & pathBad)1126 {1127 const std::string & path = osgDB::convertFileNameToNativeStyle(pathBad);1128 1129 std::string parent = "";1130 std::string tmp = "";1131 for(std::string::const_iterator itPath = path.begin();; ++itPath)1132 {1133 if (!parent.empty())1134 parent += '\\';1135 parent += tmp;1136 tmp.clear();1137 for(;itPath != path.end() && *itPath != '\\'; ++itPath)1138 tmp += *itPath;1139 if (itPath == path.end())1140 break;1141 }1142 return parent;1143 }1144 1145 1143 bool ReaderWriter3DS::createFileObject(const osg::Node& node, Lib3dsFile * file3ds,const std::string& fileName, const osgDB::ReaderWriter::Options* options) const { 1146 WriterNodeVisitor w(file3ds, fileName, options, getParent(node.getName()));1147 const_cast<osg::Node &>(node).accept(w); // TODO Remove that ugly const_cast<>. Any idea?1144 WriterNodeVisitor w(file3ds, fileName, options, osgDB::getFilePath(node.getName())); 1145 const_cast<osg::Node &>(node).accept(w); // Ugly const_cast<> for visitor... 1148 1146 if (!w.suceedLastApply()) 1149 1147 return false; … … 1151 1149 return true; //w.good(); 1152 1150 } 1153 #endif // ENABLE_3DS_WRITER 1151
