| 1 | |
|---|
| 2 | #include <osg/Notify> |
|---|
| 3 | #include <osgDB/FileUtils> |
|---|
| 4 | #include <osgDB/FileNameUtils> |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | #include <Inventor/SoDB.h> |
|---|
| 8 | #include <Inventor/SoInteraction.h> |
|---|
| 9 | #include <Inventor/nodekits/SoNodeKit.h> |
|---|
| 10 | #include <Inventor/errors/SoDebugError.h> |
|---|
| 11 | #include <Inventor/errors/SoMemoryError.h> |
|---|
| 12 | #include <Inventor/errors/SoReadError.h> |
|---|
| 13 | #include <Inventor/nodes/SoSeparator.h> |
|---|
| 14 | #include <Inventor/actions/SoWriteAction.h> |
|---|
| 15 | #include <Inventor/actions/SoCallbackAction.h> |
|---|
| 16 | #ifdef __COIN__ |
|---|
| 17 | # include <Inventor/VRMLnodes/SoVRMLImageTexture.h> |
|---|
| 18 | #endif |
|---|
| 19 | |
|---|
| 20 | #include "ReaderWriterIV.h" |
|---|
| 21 | #include "ConvertFromInventor.h" |
|---|
| 22 | #include "ConvertToInventor.h" |
|---|
| 23 | |
|---|
| 24 | |
|---|
| 25 | static void addSearchPaths(const osgDB::FilePathList *searchPaths); |
|---|
| 26 | static void removeSearchPaths(const osgDB::FilePathList *searchPaths); |
|---|
| 27 | static void errorCallback(const SoError *error, void * data); |
|---|
| 28 | |
|---|
| 29 | |
|---|
| 30 | |
|---|
| 31 | REGISTER_OSGPLUGIN(Inventor, ReaderWriterIV) |
|---|
| 32 | |
|---|
| 33 | |
|---|
| 34 | |
|---|
| 35 | |
|---|
| 36 | |
|---|
| 37 | |
|---|
| 38 | ReaderWriterIV::ReaderWriterIV() |
|---|
| 39 | { |
|---|
| 40 | |
|---|
| 41 | supportsExtension("iv","Inventor format"); |
|---|
| 42 | supportsExtension("wrl","VRML world file"); |
|---|
| 43 | |
|---|
| 44 | |
|---|
| 45 | initInventor(); |
|---|
| 46 | } |
|---|
| 47 | |
|---|
| 48 | |
|---|
| 49 | |
|---|
| 50 | |
|---|
| 51 | |
|---|
| 52 | void ReaderWriterIV::initInventor() const |
|---|
| 53 | { |
|---|
| 54 | |
|---|
| 55 | SoDB::init(); |
|---|
| 56 | SoNodeKit::init(); |
|---|
| 57 | SoInteraction::init(); |
|---|
| 58 | |
|---|
| 59 | |
|---|
| 60 | SoError::setHandlerCallback(errorCallback, NULL); |
|---|
| 61 | SoDebugError::setHandlerCallback(errorCallback, NULL); |
|---|
| 62 | SoMemoryError::setHandlerCallback(errorCallback, NULL); |
|---|
| 63 | SoReadError::setHandlerCallback(errorCallback, NULL); |
|---|
| 64 | |
|---|
| 65 | #ifdef __COIN__ |
|---|
| 66 | |
|---|
| 67 | SoVRMLImageTexture::setDelayFetchURL(FALSE); |
|---|
| 68 | |
|---|
| 69 | |
|---|
| 70 | ConvertFromInventor::init(); |
|---|
| 71 | #endif |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | |
|---|
| 75 | static void errorCallback(const SoError *error, void *data) |
|---|
| 76 | { |
|---|
| 77 | |
|---|
| 78 | |
|---|
| 79 | |
|---|
| 80 | |
|---|
| 81 | if (error->isOfType(SoDebugError::getClassTypeId())) |
|---|
| 82 | { |
|---|
| 83 | switch (((SoDebugError*)error)->getSeverity()) |
|---|
| 84 | { |
|---|
| 85 | case SoDebugError::INFO: |
|---|
| 86 | OSG_INFO << error->getDebugString().getString() << std::endl; |
|---|
| 87 | break; |
|---|
| 88 | case SoDebugError::WARNING: |
|---|
| 89 | OSG_WARN << error->getDebugString().getString() << std::endl; |
|---|
| 90 | break; |
|---|
| 91 | case SoDebugError::ERROR: |
|---|
| 92 | default: |
|---|
| 93 | OSG_WARN << error->getDebugString().getString() << std::endl; |
|---|
| 94 | break; |
|---|
| 95 | } |
|---|
| 96 | } |
|---|
| 97 | else |
|---|
| 98 | { |
|---|
| 99 | OSG_WARN << error->getDebugString().getString() << std::endl; |
|---|
| 100 | } |
|---|
| 101 | } |
|---|
| 102 | |
|---|
| 103 | |
|---|
| 104 | |
|---|
| 105 | |
|---|
| 106 | |
|---|
| 107 | |
|---|
| 108 | osgDB::ReaderWriter::ReadResult |
|---|
| 109 | ReaderWriterIV::readNodeFromSoInput(SoInput &input, |
|---|
| 110 | std::string &fileName, const osgDB::ReaderWriter::Options *options) const |
|---|
| 111 | { |
|---|
| 112 | |
|---|
| 113 | const osgDB::FilePathList *searchPaths = options ? &options->getDatabasePathList() : NULL; |
|---|
| 114 | if (options) |
|---|
| 115 | addSearchPaths(searchPaths); |
|---|
| 116 | |
|---|
| 117 | |
|---|
| 118 | SoSeparator* rootIVNode = SoDB::readAll(&input); |
|---|
| 119 | |
|---|
| 120 | |
|---|
| 121 | if (options) |
|---|
| 122 | removeSearchPaths(searchPaths); |
|---|
| 123 | |
|---|
| 124 | |
|---|
| 125 | input.closeFile(); |
|---|
| 126 | |
|---|
| 127 | |
|---|
| 128 | ReadResult result; |
|---|
| 129 | if (rootIVNode) |
|---|
| 130 | { |
|---|
| 131 | rootIVNode->ref(); |
|---|
| 132 | |
|---|
| 133 | ConvertFromInventor convertIV; |
|---|
| 134 | convertIV.preprocess(rootIVNode); |
|---|
| 135 | result = convertIV.convert(rootIVNode); |
|---|
| 136 | rootIVNode->unref(); |
|---|
| 137 | } else |
|---|
| 138 | result = ReadResult::FILE_NOT_HANDLED; |
|---|
| 139 | |
|---|
| 140 | |
|---|
| 141 | if (result.success()) { |
|---|
| 142 | if (fileName.length()) |
|---|
| 143 | { |
|---|
| 144 | OSG_NOTICE << "osgDB::ReaderWriterIV::readNode() " |
|---|
| 145 | << "File " << fileName.data() |
|---|
| 146 | << " loaded successfully." << std::endl; |
|---|
| 147 | } |
|---|
| 148 | else |
|---|
| 149 | { |
|---|
| 150 | OSG_NOTICE << "osgDB::ReaderWriterIV::readNode() " |
|---|
| 151 | << "Stream loaded successfully." << std::endl; |
|---|
| 152 | } |
|---|
| 153 | } else { |
|---|
| 154 | if (fileName.length()) |
|---|
| 155 | { |
|---|
| 156 | OSG_WARN << "osgDB::ReaderWriterIV::readNode() " |
|---|
| 157 | << "Failed to load file " << fileName.data() |
|---|
| 158 | << "." << std::endl; |
|---|
| 159 | } |
|---|
| 160 | else |
|---|
| 161 | { |
|---|
| 162 | OSG_WARN << "osgDB::ReaderWriterIV::readNode() " |
|---|
| 163 | << "Failed to load stream." << std::endl; |
|---|
| 164 | } |
|---|
| 165 | } |
|---|
| 166 | |
|---|
| 167 | return result; |
|---|
| 168 | } |
|---|
| 169 | |
|---|
| 170 | |
|---|
| 171 | |
|---|
| 172 | osgDB::ReaderWriter::ReadResult |
|---|
| 173 | ReaderWriterIV::readNode(const std::string& file, |
|---|
| 174 | const osgDB::ReaderWriter::Options* options) const |
|---|
| 175 | { |
|---|
| 176 | |
|---|
| 177 | std::string ext = osgDB::getLowerCaseFileExtension(file); |
|---|
| 178 | if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; |
|---|
| 179 | |
|---|
| 180 | |
|---|
| 181 | std::string fileName = osgDB::findDataFile( file, options ); |
|---|
| 182 | if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; |
|---|
| 183 | |
|---|
| 184 | |
|---|
| 185 | OSG_NOTICE << "osgDB::ReaderWriterIV::readNode() Reading file " |
|---|
| 186 | << fileName.data() << std::endl; |
|---|
| 187 | OSG_INFO << "osgDB::ReaderWriterIV::readNode() Inventor version: " |
|---|
| 188 | << SoDB::getVersion() << std::endl; |
|---|
| 189 | |
|---|
| 190 | |
|---|
| 191 | SoInput input; |
|---|
| 192 | if (!input.openFile(fileName.data())) |
|---|
| 193 | { |
|---|
| 194 | OSG_WARN << "osgDB::ReaderWriterIV::readIVFile() " |
|---|
| 195 | << "Cannot open file " << fileName << std::endl; |
|---|
| 196 | return ReadResult::ERROR_IN_READING_FILE; |
|---|
| 197 | } |
|---|
| 198 | |
|---|
| 199 | |
|---|
| 200 | return readNodeFromSoInput(input, fileName, options); |
|---|
| 201 | } |
|---|
| 202 | |
|---|
| 203 | |
|---|
| 204 | osgDB::ReaderWriter::ReadResult |
|---|
| 205 | ReaderWriterIV::readNode(std::istream& fin, |
|---|
| 206 | const osgDB::ReaderWriter::Options* options) const |
|---|
| 207 | { |
|---|
| 208 | |
|---|
| 209 | OSG_NOTICE << "osgDB::ReaderWriterIV::readNode() " |
|---|
| 210 | "Reading from stream." << std::endl; |
|---|
| 211 | OSG_INFO << "osgDB::ReaderWriterIV::readNode() " |
|---|
| 212 | "Inventor version: " << SoDB::getVersion() << std::endl; |
|---|
| 213 | |
|---|
| 214 | |
|---|
| 215 | SoInput input; |
|---|
| 216 | |
|---|
| 217 | |
|---|
| 218 | |
|---|
| 219 | |
|---|
| 220 | |
|---|
| 221 | |
|---|
| 222 | |
|---|
| 223 | |
|---|
| 224 | |
|---|
| 225 | |
|---|
| 226 | |
|---|
| 227 | |
|---|
| 228 | |
|---|
| 229 | size_t bufSize = 126*1024; |
|---|
| 230 | char *buf = (char*)malloc(bufSize); |
|---|
| 231 | size_t dataSize = 0; |
|---|
| 232 | while (!fin.eof() && fin.good()) { |
|---|
| 233 | fin.read(buf+dataSize, bufSize-dataSize); |
|---|
| 234 | dataSize += fin.gcount(); |
|---|
| 235 | if (bufSize == dataSize) { |
|---|
| 236 | bufSize *= 2; |
|---|
| 237 | char* new_buf = (char*)realloc(buf, bufSize); |
|---|
| 238 | if (!new_buf) |
|---|
| 239 | { |
|---|
| 240 | free(buf); |
|---|
| 241 | return osgDB::ReaderWriter::ReadResult::INSUFFICIENT_MEMORY_TO_LOAD; |
|---|
| 242 | } |
|---|
| 243 | buf = new_buf; |
|---|
| 244 | } |
|---|
| 245 | } |
|---|
| 246 | input.setBuffer(buf, dataSize); |
|---|
| 247 | OSG_INFO << "osgDB::ReaderWriterIV::readNode() " |
|---|
| 248 | "Stream size: " << dataSize << std::endl; |
|---|
| 249 | |
|---|
| 250 | |
|---|
| 251 | osgDB::ReaderWriter::ReadResult r; |
|---|
| 252 | std::string fileName(""); |
|---|
| 253 | r = readNodeFromSoInput(input, fileName, options); |
|---|
| 254 | |
|---|
| 255 | |
|---|
| 256 | free(buf); |
|---|
| 257 | return r; |
|---|
| 258 | } |
|---|
| 259 | |
|---|
| 260 | |
|---|
| 261 | osgDB::ReaderWriter::WriteResult |
|---|
| 262 | ReaderWriterIV::writeNode(const osg::Node& node, const std::string& fileName, |
|---|
| 263 | const osgDB::ReaderWriter::Options* options) const |
|---|
| 264 | { |
|---|
| 265 | |
|---|
| 266 | std::string ext = osgDB::getLowerCaseFileExtension(fileName); |
|---|
| 267 | if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; |
|---|
| 268 | bool useVRML1 = !isInventorExtension(osgDB::getFileExtension(fileName)); |
|---|
| 269 | |
|---|
| 270 | OSG_NOTICE << "osgDB::ReaderWriterIV::writeNode() Writing file " |
|---|
| 271 | << fileName.data() << std::endl; |
|---|
| 272 | |
|---|
| 273 | |
|---|
| 274 | ConvertToInventor osg2iv; |
|---|
| 275 | osg2iv.setVRML1Conversion(useVRML1); |
|---|
| 276 | (const_cast<osg::Node*>(&node))->accept(osg2iv); |
|---|
| 277 | SoNode *ivRoot = osg2iv.getIvSceneGraph(); |
|---|
| 278 | if (ivRoot == NULL) |
|---|
| 279 | return WriteResult::ERROR_IN_WRITING_FILE; |
|---|
| 280 | ivRoot->ref(); |
|---|
| 281 | |
|---|
| 282 | |
|---|
| 283 | |
|---|
| 284 | |
|---|
| 285 | |
|---|
| 286 | if (useVRML1) |
|---|
| 287 | SoBase::setInstancePrefix("_"); |
|---|
| 288 | |
|---|
| 289 | |
|---|
| 290 | SoOutput out; |
|---|
| 291 | out.setHeaderString((useVRML1) ? "#VRML V1.0 ascii" : "#Inventor V2.1 ascii"); |
|---|
| 292 | if (!out.openFile(fileName.c_str())) |
|---|
| 293 | return WriteResult::ERROR_IN_WRITING_FILE; |
|---|
| 294 | SoWriteAction wa(&out); |
|---|
| 295 | wa.apply(ivRoot); |
|---|
| 296 | ivRoot->unref(); |
|---|
| 297 | |
|---|
| 298 | return WriteResult::FILE_SAVED; |
|---|
| 299 | } |
|---|
| 300 | |
|---|
| 301 | |
|---|
| 302 | static void addSearchPaths(const osgDB::FilePathList *searchPaths) |
|---|
| 303 | { |
|---|
| 304 | for (int i=searchPaths->size()-1; i>=0; i--) |
|---|
| 305 | SoInput::addDirectoryFirst(searchPaths->operator[](i).c_str()); |
|---|
| 306 | } |
|---|
| 307 | |
|---|
| 308 | |
|---|
| 309 | static void removeSearchPaths(const osgDB::FilePathList *searchPaths) |
|---|
| 310 | { |
|---|
| 311 | for (int i=0, c=searchPaths->size(); i<c; i++) |
|---|
| 312 | SoInput::addDirectoryFirst(searchPaths->operator[](i).c_str()); |
|---|
| 313 | } |
|---|