root/OpenSceneGraph/trunk/src/osgPlugins/Inventor/ReaderWriterIV.cpp @ 11032

Revision 11032, 8.2 kB (checked in by robert, 4 years ago)

From Jan Peciva, "I am sending improved version of Inventor plugin. Attaching just
modified files, while GroupSoLOD.h and .cpp was deleted. Please, delete
it from repository, it is not used any longer and I doubt if it is
probably not used for anything meaningful for a while. In the new code,
there is no GroupSoLOD. Please, delete it.

I am using new plugin version for about 1.5 month so I consider it
stable by myself.

List of changes:
- rewritten Inventor state stack
- shaders support
- light attenuation support
- support for reading from stream (readNode(std::istream& fin, options))
- improved grouping node handling (SoSeparator?, SoGroup?,...)
- fixed transformation bug when two SoShapes/Drawables? with different transformations are placed bellow one grouping node
- introduced preprocessing to handle more advanced usage schemes of SoLOD and SoSwitch? nodes
- unused code clean up
- improved notify messages
- animation callbacks fixes
- FindInventor?.cmake improved finding routines, support for Coin3 and Coin4"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[2225]1// OSG headers
2#include <osg/Notify>
[2759]3#include <osgDB/FileUtils>
[2225]4#include <osgDB/FileNameUtils>
5
6// Inventor headers
[3920]7#include <Inventor/SoDB.h>
[2225]8#include <Inventor/SoInteraction.h>
[3920]9#include <Inventor/nodekits/SoNodeKit.h>
[2225]10#include <Inventor/nodes/SoSeparator.h>
[7348]11#include <Inventor/actions/SoWriteAction.h>
12#include <Inventor/actions/SoCallbackAction.h>
[7512]13#ifdef __COIN__
[11032]14# include <Inventor/VRMLnodes/SoVRMLImageTexture.h>
[6544]15#endif
[2225]16
[11032]17#include "ReaderWriterIV.h"
[2225]18#include "ConvertFromInventor.h"
[7348]19#include "ConvertToInventor.h"
[2225]20
[11032]21// forward declarations of static functions
22static void addSearchPaths(const osgDB::FilePathList *searchPaths);
23static void removeSearchPaths(const osgDB::FilePathList *searchPaths);
[7348]24
[11032]25
[2225]26// Register with Registry to instantiate the inventor reader.
[7076]27REGISTER_OSGPLUGIN(Inventor, ReaderWriterIV)
[2225]28
[11032]29
30/**
31 * Constructor.
32 * Initializes the ReaderWriterIV.
33 */
[2225]34ReaderWriterIV::ReaderWriterIV()
35{
[11032]36    // Set supported extensions and options
[8578]37    supportsExtension("iv","Inventor format");
38    supportsExtension("wrl","VRML world file");
[11032]39
40    // Initialize Inventor
41    initInventor();
[2225]42}
43
[11032]44
45/**
46 * Initializes Open Inventor.
47 */
48void ReaderWriterIV::initInventor() const
[2225]49{
50    // Initialize Inventor
[3920]51    SoDB::init();
52    SoNodeKit::init();
[2225]53    SoInteraction::init();
54
[7512]55#ifdef __COIN__
[6543]56    // Disable delayed loading of VRML textures
57    SoVRMLImageTexture::setDelayFetchURL(FALSE);
[6544]58#endif
[11032]59}
[6543]60
[2225]61
[11032]62/**
63 * Read from SoInput and convert to OSG.
64 * This is a method used by readNode(string,options) and readNode(istream,options).
65 */
66osgDB::ReaderWriter::ReadResult
67ReaderWriterIV::readNodeFromSoInput(SoInput &input,
68          std::string &fileName, const osgDB::ReaderWriter::Options *options) const
69{
70    // Parse options and add search paths to SoInput
71    const osgDB::FilePathList *searchPaths = options ? &options->getDatabasePathList() : NULL;
72    if (options)
73        addSearchPaths(searchPaths);
74
75    // Create the inventor scenegraph by reading from SoInput
[2225]76    SoSeparator* rootIVNode = SoDB::readAll(&input);
77
[11032]78    // Remove recently appened search paths
79    if (options)
80        removeSearchPaths(searchPaths);
81
[2225]82    // Close the file
83    input.closeFile();
84
[11032]85    // Perform conversion
86    ReadResult result;
[2225]87    if (rootIVNode)
88    {
[3393]89        rootIVNode->ref();
[11032]90        // Convert the inventor scenegraph to an osg scenegraph
[2225]91        ConvertFromInventor convertIV;
[11032]92        convertIV.preprocess(rootIVNode);
93        result = convertIV.convert(rootIVNode);
[3393]94        rootIVNode->unref();
[11032]95    } else
96        result = ReadResult::FILE_NOT_HANDLED;
97
98    // Notify
99    if (result.success()) {
100        if (fileName.length())
101            osg::notify(osg::NOTICE) << "osgDB::ReaderWriterIV::readNode() "
102                      << "File " << fileName.data()
103                      << " loaded successfully." << std::endl;
104        else
105            osg::notify(osg::NOTICE) << "osgDB::ReaderWriterIV::readNode() "
106                      << "Stream loaded successfully." << std::endl;
107    } else {
108        if (fileName.length())
109            osg::notify(osg::WARN) << "osgDB::ReaderWriterIV::readNode() "
110                      << "Failed to load file " << fileName.data()
111                      << "." << std::endl;
112        else
113            osg::notify(osg::WARN) << "osgDB::ReaderWriterIV::readNode() "
114                  << "Failed to load stream." << std::endl;
[2225]115    }
116
[11032]117    return result;
[2225]118}
119
[7348]120
[11032]121// Read file and convert to OSG
122osgDB::ReaderWriter::ReadResult
123ReaderWriterIV::readNode(const std::string& file,
124                         const osgDB::ReaderWriter::Options* options) const
125{
126    // Accept extension
127    std::string ext = osgDB::getLowerCaseFileExtension(file);
128    if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
129
130    // Find file
131    std::string fileName = osgDB::findDataFile( file, options );
132    if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
133
134    // Notify
135    osg::notify(osg::NOTICE) << "osgDB::ReaderWriterIV::readNode() Reading file "
136                             << fileName.data() << std::endl;
137    osg::notify(osg::INFO) << "osgDB::ReaderWriterIV::readNode() Inventor version: "
138                           << SoDB::getVersion() << std::endl;
139
140    // Open the file
141    SoInput input;
142    if (!input.openFile(fileName.data()))
143    {
144        osg::notify(osg::WARN) << "osgDB::ReaderWriterIV::readIVFile() "
145                               << "Cannot open file " << fileName << std::endl;
146        return ReadResult::ERROR_IN_READING_FILE;
147    }
148
149    // Perform reading from SoInput
150    return readNodeFromSoInput(input, fileName, options);
151}
152
153
154osgDB::ReaderWriter::ReadResult
155ReaderWriterIV::readNode(std::istream& fin,
156                         const osgDB::ReaderWriter::Options* options) const
157{
158    // Notify
159    osg::notify(osg::NOTICE) << "osgDB::ReaderWriterIV::readNode() "
160              "Reading from stream." << std::endl;
161    osg::notify(osg::INFO) << "osgDB::ReaderWriterIV::readNode() "
162              "Inventor version: " << SoDB::getVersion() << std::endl;
163
164    // Open the file
165    SoInput input;
166
167    // Assign istream to SoInput
168    // note: It seems there is no straightforward way to do that.
169    // SoInput accepts only FILE by setFilePointer or memory buffer
170    // by setBuffer. The FILE is dangerous on Windows, since it forces
171    // the plugin and Inventor DLL to use the same runtime library
172    // (otherwise there are app crashes).
173    // The memory buffer seems much better option here, even although
174    // there will not be a real streaming. However, the model data
175    // are usually much smaller than textures, so we should not worry
176    // about it and think how to stream textures instead.
177
178    // Get the data to the buffer
179    size_t bufSize = 126*1024; // let's make it something bellow 128KB
180    char *buf = (char*)malloc(bufSize);
181    size_t dataSize = 0;
182    while (!fin.eof() && fin.good()) {
183        fin.read(buf+dataSize, bufSize-dataSize);
184        dataSize += fin.gcount();
185        if (bufSize == dataSize) {
186           bufSize *= 2;
187           buf = (char*)realloc(buf, bufSize);
188        }
189    }
190    input.setBuffer(buf, dataSize);
191    osg::notify(osg::INFO) << "osgDB::ReaderWriterIV::readNode() "
192              "Stream size: " << dataSize << std::endl;
193
194    // Perform reading from SoInput
195    osgDB::ReaderWriter::ReadResult r;
196    std::string fileName("");
197    r = readNodeFromSoInput(input, fileName, options);
198
199    // clean up and return
200    free(buf);
201    return r;
202}
203
204
[7348]205osgDB::ReaderWriter::WriteResult
206ReaderWriterIV::writeNode(const osg::Node& node, const std::string& fileName,
207                          const osgDB::ReaderWriter::Options* options) const
208{
209    // accept extension
210    std::string ext = osgDB::getLowerCaseFileExtension(fileName);
211    if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
212    bool useVRML1 = !isInventorExtension(osgDB::getFileExtension(fileName));
213
[11032]214    osg::notify(osg::NOTICE) << "osgDB::ReaderWriterIV::writeNode() Writing file "
215                             << fileName.data() << std::endl;
[7348]216
217    // Convert OSG graph to Inventor graph
218    ConvertToInventor osg2iv;
219    osg2iv.setVRML1Conversion(useVRML1);
220    (const_cast<osg::Node*>(&node))->accept(osg2iv);
221    SoNode *ivRoot = osg2iv.getIvSceneGraph();
222    if (ivRoot == NULL)
223        return WriteResult::ERROR_IN_WRITING_FILE;
224    ivRoot->ref();
225
226    // Change prefix according to VRML spec:
227    // Node names must not begin with a digit, and must not contain spaces or
228    // control characters, single or double quote characters, backslashes, curly braces,
229    // the sharp (#) character, the plus (+) character or the period character.
230    if (useVRML1)
231      SoBase::setInstancePrefix("_");
232
233    // Write Inventor graph to file
234    SoOutput out;
235    out.setHeaderString((useVRML1) ? "#VRML V1.0 ascii" : "#Inventor V2.1 ascii");
236    if (!out.openFile(fileName.c_str()))
237        return WriteResult::ERROR_IN_WRITING_FILE;
238    SoWriteAction wa(&out);
239    wa.apply(ivRoot);
240    ivRoot->unref();
241
242    return WriteResult::FILE_SAVED;
243}
[11032]244
245
246static void addSearchPaths(const osgDB::FilePathList *searchPaths)
247{
248    for (int i=searchPaths->size()-1; i>=0; i--)
249        SoInput::addDirectoryFirst(searchPaths->operator[](i).c_str());
250}
251
252
253static void removeSearchPaths(const osgDB::FilePathList *searchPaths)
254{
255    for (int i=0, c=searchPaths->size(); i<c; i++)
256        SoInput::addDirectoryFirst(searchPaths->operator[](i).c_str());
257}
Note: See TracBrowser for help on using the browser.