Index: OpenSceneGraph/trunk/src/osgPlugins/Inventor/ReaderWriterIV.cpp
===================================================================
--- OpenSceneGraph/trunk/src/osgPlugins/Inventor/ReaderWriterIV.cpp (revision 8578)
+++ OpenSceneGraph/trunk/src/osgPlugins/Inventor/ReaderWriterIV.cpp (revision 11032)
@@ -1,4 +1,2 @@
-#include "ReaderWriterIV.h"
-
 // OSG headers
 #include <osg/Notify>
@@ -13,12 +11,15 @@
 #include <Inventor/actions/SoWriteAction.h>
 #include <Inventor/actions/SoCallbackAction.h>
-
 #ifdef __COIN__
-#include <Inventor/VRMLnodes/SoVRMLImageTexture.h>
+# include <Inventor/VRMLnodes/SoVRMLImageTexture.h>
 #endif
 
+#include "ReaderWriterIV.h"
 #include "ConvertFromInventor.h"
-#include "GroupSoLOD.h"
 #include "ConvertToInventor.h"
+
+// forward declarations of static functions
+static void addSearchPaths(const osgDB::FilePathList *searchPaths);
+static void removeSearchPaths(const osgDB::FilePathList *searchPaths);
 
 
@@ -26,32 +27,29 @@
 REGISTER_OSGPLUGIN(Inventor, ReaderWriterIV)
 
+
+/**
+ * Constructor.
+ * Initializes the ReaderWriterIV.
+ */
 ReaderWriterIV::ReaderWriterIV()
 {
+    // Set supported extensions and options
     supportsExtension("iv","Inventor format");
     supportsExtension("wrl","VRML world file");
-}
-
-// Read file and convert to OSG
-osgDB::ReaderWriter::ReadResult 
-ReaderWriterIV::readNode(const std::string& file,
-                         const osgDB::ReaderWriter::Options* options) const
-{
-    std::string ext = osgDB::getLowerCaseFileExtension(file);
-    if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
-
-    std::string fileName = osgDB::findDataFile( file, options );
-    if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
-
-    osg::notify(osg::INFO) << "osgDB::ReaderWriterIV::readNode() Reading file " 
-                           << fileName.data() << std::endl;
-    
+
+    // Initialize Inventor
+    initInventor();
+}
+
+
+/**
+ * Initializes Open Inventor.
+ */
+void ReaderWriterIV::initInventor() const
+{
     // Initialize Inventor
     SoDB::init();
     SoNodeKit::init();
     SoInteraction::init();
-    
-
-    // Initial GroupSoLOD node
-    GroupSoLOD::initClass();
 
 #ifdef __COIN__
@@ -59,4 +57,84 @@
     SoVRMLImageTexture::setDelayFetchURL(FALSE);
 #endif
+}
+
+
+/**
+ * Read from SoInput and convert to OSG.
+ * This is a method used by readNode(string,options) and readNode(istream,options).
+ */
+osgDB::ReaderWriter::ReadResult
+ReaderWriterIV::readNodeFromSoInput(SoInput &input,
+          std::string &fileName, const osgDB::ReaderWriter::Options *options) const
+{
+    // Parse options and add search paths to SoInput
+    const osgDB::FilePathList *searchPaths = options ? &options->getDatabasePathList() : NULL;
+    if (options)
+        addSearchPaths(searchPaths);
+
+    // Create the inventor scenegraph by reading from SoInput
+    SoSeparator* rootIVNode = SoDB::readAll(&input);
+
+    // Remove recently appened search paths
+    if (options)
+        removeSearchPaths(searchPaths);
+
+    // Close the file
+    input.closeFile();
+
+    // Perform conversion
+    ReadResult result;
+    if (rootIVNode)
+    {
+        rootIVNode->ref();
+        // Convert the inventor scenegraph to an osg scenegraph
+        ConvertFromInventor convertIV;
+        convertIV.preprocess(rootIVNode);
+        result = convertIV.convert(rootIVNode);
+        rootIVNode->unref();
+    } else
+        result = ReadResult::FILE_NOT_HANDLED;
+
+    // Notify
+    if (result.success()) {
+        if (fileName.length())
+            osg::notify(osg::NOTICE) << "osgDB::ReaderWriterIV::readNode() "
+                      << "File " << fileName.data()
+                      << " loaded successfully." << std::endl;
+        else
+            osg::notify(osg::NOTICE) << "osgDB::ReaderWriterIV::readNode() "
+                      << "Stream loaded successfully." << std::endl;
+    } else {
+        if (fileName.length())
+            osg::notify(osg::WARN) << "osgDB::ReaderWriterIV::readNode() "
+                      << "Failed to load file " << fileName.data()
+                      << "." << std::endl;
+        else
+            osg::notify(osg::WARN) << "osgDB::ReaderWriterIV::readNode() "
+                  << "Failed to load stream." << std::endl;
+    }
+
+    return result;
+}
+
+
+// Read file and convert to OSG
+osgDB::ReaderWriter::ReadResult
+ReaderWriterIV::readNode(const std::string& file,
+                         const osgDB::ReaderWriter::Options* options) const
+{
+    // Accept extension
+    std::string ext = osgDB::getLowerCaseFileExtension(file);
+    if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
+
+    // Find file
+    std::string fileName = osgDB::findDataFile( file, options );
+    if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
+
+    // Notify
+    osg::notify(osg::NOTICE) << "osgDB::ReaderWriterIV::readNode() Reading file "
+                             << fileName.data() << std::endl;
+    osg::notify(osg::INFO) << "osgDB::ReaderWriterIV::readNode() Inventor version: "
+                           << SoDB::getVersion() << std::endl;
 
     // Open the file
@@ -69,21 +147,57 @@
     }
 
-    // Create the inventor scenegraph from the file
-    SoSeparator* rootIVNode = SoDB::readAll(&input);
-
-    // Close the file
-    input.closeFile();
-
-    if (rootIVNode)
-    {
-        rootIVNode->ref();
-        // Convert the inventor scenegraph to an osg scenegraph and return it
-        ConvertFromInventor convertIV;
-        ReadResult result = convertIV.convert(rootIVNode);
-        rootIVNode->unref();
-        return result;
+    // Perform reading from SoInput
+    return readNodeFromSoInput(input, fileName, options);
+}
+
+
+osgDB::ReaderWriter::ReadResult
+ReaderWriterIV::readNode(std::istream& fin,
+                         const osgDB::ReaderWriter::Options* options) const
+{
+    // Notify
+    osg::notify(osg::NOTICE) << "osgDB::ReaderWriterIV::readNode() "
+              "Reading from stream." << std::endl;
+    osg::notify(osg::INFO) << "osgDB::ReaderWriterIV::readNode() "
+              "Inventor version: " << SoDB::getVersion() << std::endl;
+
+    // Open the file
+    SoInput input;
+
+    // Assign istream to SoInput
+    // note: It seems there is no straightforward way to do that.
+    // SoInput accepts only FILE by setFilePointer or memory buffer
+    // by setBuffer. The FILE is dangerous on Windows, since it forces
+    // the plugin and Inventor DLL to use the same runtime library
+    // (otherwise there are app crashes).
+    // The memory buffer seems much better option here, even although
+    // there will not be a real streaming. However, the model data
+    // are usually much smaller than textures, so we should not worry
+    // about it and think how to stream textures instead.
+
+    // Get the data to the buffer
+    size_t bufSize = 126*1024; // let's make it something bellow 128KB
+    char *buf = (char*)malloc(bufSize);
+    size_t dataSize = 0;
+    while (!fin.eof() && fin.good()) {
+        fin.read(buf+dataSize, bufSize-dataSize);
+        dataSize += fin.gcount();
+        if (bufSize == dataSize) {
+           bufSize *= 2;
+           buf = (char*)realloc(buf, bufSize);
+        }
     }
-
-    return ReadResult::FILE_NOT_HANDLED;
+    input.setBuffer(buf, dataSize);
+    osg::notify(osg::INFO) << "osgDB::ReaderWriterIV::readNode() "
+              "Stream size: " << dataSize << std::endl;
+
+    // Perform reading from SoInput
+    osgDB::ReaderWriter::ReadResult r;
+    std::string fileName("");
+    r = readNodeFromSoInput(input, fileName, options);
+
+    // clean up and return
+    free(buf);
+    return r;
 }
 
@@ -98,9 +212,6 @@
     bool useVRML1 = !isInventorExtension(osgDB::getFileExtension(fileName));
 
-    osg::notify(osg::INFO) << "osgDB::ReaderWriterIV::writeNode() Writing file " 
-                           << fileName.data() << std::endl;
-    
-    // Initialize Inventor
-    SoInteraction::init();
+    osg::notify(osg::NOTICE) << "osgDB::ReaderWriterIV::writeNode() Writing file "
+                             << fileName.data() << std::endl;
 
     // Convert OSG graph to Inventor graph
@@ -131,2 +242,17 @@
     return WriteResult::FILE_SAVED;
 }
+
+
+static void addSearchPaths(const osgDB::FilePathList *searchPaths)
+{
+    for (int i=searchPaths->size()-1; i>=0; i--)
+        SoInput::addDirectoryFirst(searchPaths->operator[](i).c_str());
+}
+
+
+static void removeSearchPaths(const osgDB::FilePathList *searchPaths)
+{
+    for (int i=0, c=searchPaths->size(); i<c; i++)
+        SoInput::addDirectoryFirst(searchPaths->operator[](i).c_str());
+}
+
