From Jan Peciva, Added write support into Inventor plugin.

Note from Robert Osfield.  A couple of lines of code in ConvertToInventor.cpp
would not compile under g++ 4.1.2, so rather than hold back the dev release till
this is resolved I've optional compiled out the problem section.
The #define DISABLE_PROBLEM_COMPILE_SECTIONS is used to compile out the problem
section, this define is add via the CMakeLists.txt file.
This commit is contained in:
Robert Osfield
2007-09-03 13:52:19 +00:00
parent 7b73a58728
commit bd845a7b23
7 changed files with 2138 additions and 58 deletions

View File

@@ -2,21 +2,25 @@ INCLUDE(OsgMacroUtils)
INCLUDE_DIRECTORIES( ${INVENTOR_INCLUDE_DIR} )
# Disable the build of a problem section in ConvertToInventor.cpp
ADD_DEFINITIONS(-DDISABLE_PROBLEM_COMPILE_SECTIONS)
SET(TARGET_SRC
ConvertToInventor.cpp
ConvertFromInventor.cpp
GroupSoLOD.cpp
PendulumCallback.cpp
ReaderWriterIV.cpp
ShuttleCallback.cpp
)
)
SET(TARGET_HDRS
ConvertToInventor.h
ConvertFromInventor.h
GroupSoLOD.h
PendulumCallback.h
ReaderWriterIV.h
ShuttleCallback.h
)
)
SET(TARGET_EXTERNAL_LIBRARIES ${INVENTOR_LIBRARY} )

View File

@@ -40,7 +40,7 @@
#include <Inventor/SoPrimitiveVertex.h>
#include <Inventor/SbLinear.h>
#ifdef COIN_BASIC_H
#ifdef __COIN__
#include <Inventor/VRMLnodes/SoVRMLImageTexture.h>
#endif
@@ -95,7 +95,7 @@ osg::Node* ConvertFromInventor::convert(SoNode* rootIVNode)
cbAction.addPreCallback(SoGroup::getClassTypeId(), preGroup, this);
cbAction.addPostCallback(SoGroup::getClassTypeId(), postGroup, this);
cbAction.addPreCallback(SoTexture2::getClassTypeId(), preTexture, this);
#ifdef COIN_BASIC_H
#ifdef __COIN__
cbAction.addPreCallback(SoVRMLImageTexture::getClassTypeId(),
preVRMLImageTexture, this);
#endif
@@ -498,6 +498,51 @@ ConvertFromInventor::getStateSet(SoCallbackAction* action)
// Inherit modes from the global state
stateSet->clear();
// Convert the IV texture to OSG texture if any
osg::ref_ptr<osg::Texture2D> texture;
const SoNode *ivTexture = soTexStack.top();
if (ivTexture)
{
osg::notify(osg::INFO)<<"Have texture"<<std::endl;
// Found a corresponding OSG texture object
if (ivToOsgTexMap[ivTexture])
texture = ivToOsgTexMap[ivTexture];
else
{
// Create a new osg texture
texture = convertIVTexToOSGTex(ivTexture, action);
// Add the new texture to the database
ivToOsgTexMap[ivTexture] = texture.get();
}
stateSet->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::ON);
// Set the texture environment
osg::ref_ptr<osg::TexEnv> texEnv = new osg::TexEnv;
switch (action->getTextureModel())
{
case SoTexture2::MODULATE:
texEnv->setMode(osg::TexEnv::MODULATE);
break;
case SoTexture2::DECAL:
texEnv->setMode(osg::TexEnv::DECAL);
break;
case SoTexture2::BLEND:
texEnv->setMode(osg::TexEnv::BLEND);
break;
// SGI's Inventor does not have REPLACE mode, but the Coin 3D library does.
// Coin supports REPLACE since 2.2 release, TGS Inventor from 4.0.
// Let's convert to the TexEnv anyway.
case (SoTexture2::Model)GL_REPLACE: // SoTexture2::REPLACE is the same as GL_REPLACE
texEnv->setMode(osg::TexEnv::REPLACE);
break;
}
stateSet->setTextureAttributeAndModes(0,texEnv.get(),osg::StateAttribute::ON);
}
SbColor ambient, diffuse, specular, emission;
float shininess, transparency;
@@ -506,7 +551,24 @@ ConvertFromInventor::getStateSet(SoCallbackAction* action)
shininess, transparency, 0);
// Set transparency
if (transparency > 0)
SbBool hasTextureTransparency = FALSE;
if (ivTexture) {
SbVec2s tmp;
int bpp;
if (ivTexture->isOfType(SoTexture2::getClassTypeId()))
((SoTexture2*)ivTexture)->image.getValue(tmp, bpp);
#ifdef __COIN__
else
if (ivTexture->isOfType(SoVRMLImageTexture::getClassTypeId())) {
const SbImage *img = ((SoVRMLImageTexture*)ivTexture)->getImage();
if (img) img->getValue(tmp, bpp);
else bpp = 0;
}
#endif
hasTextureTransparency = bpp==4 || bpp==2;
}
if (transparency > 0 || hasTextureTransparency)
{
osg::ref_ptr<osg::BlendFunc> transparency = new osg::BlendFunc;
stateSet->setAttributeAndModes(transparency.get(),
@@ -621,51 +683,6 @@ ConvertFromInventor::getStateSet(SoCallbackAction* action)
osg::StateAttribute::ON);
}
// Convert the IV texture to OSG texture if any
osg::ref_ptr<osg::Texture2D> texture;
if (soTexStack.top())
{
osg::notify(osg::INFO)<<"Have texture"<<std::endl;
// Found a corresponding OSG texture object
if (ivToOsgTexMap[soTexStack.top()])
texture = ivToOsgTexMap[soTexStack.top()];
else
{
// Create a new osg texture
texture = convertIVTexToOSGTex(soTexStack.top(), action);
// Add the new texture to the database
ivToOsgTexMap[soTexStack.top()] = texture.get();
}
stateSet->setTextureAttributeAndModes(0,texture.get(), osg::StateAttribute::ON);
// Set the texture environment
osg::ref_ptr<osg::TexEnv> texEnv = new osg::TexEnv;
switch (action->getTextureModel())
{
case SoTexture2::MODULATE:
texEnv->setMode(osg::TexEnv::MODULATE);
break;
case SoTexture2::DECAL:
texEnv->setMode(osg::TexEnv::DECAL);
break;
case SoTexture2::BLEND:
texEnv->setMode(osg::TexEnv::BLEND);
break;
#ifdef __COIN__
// SGI's Inventor does not have REPLACE mode, but the Coin 3D library does.
// Coin supports REPLACE since 2.2 release, TGS Inventor from 4.0.
case SoTexture2::REPLACE:
texEnv->setMode(osg::TexEnv::REPLACE);
break;
#endif
}
stateSet->setTextureAttributeAndModes(0,texEnv.get(),osg::StateAttribute::ON);
}
return stateSet;
}
////////////////////////////////////////////////////////////////////
@@ -696,7 +713,7 @@ ConvertFromInventor::convertIVTexToOSGTex(const SoNode* soNode,
std::string fileName;
if (soNode->isOfType(SoTexture2::getClassTypeId()))
fileName = ((SoTexture2*)soNode)->filename.getValue().getString();
#ifdef COIN_BASIC_H
#ifdef __COIN__
else
if (soNode->isOfType(SoVRMLImageTexture::getClassTypeId()))
fileName = ((SoVRMLImageTexture*)soNode)->url.getNum() >= 1 ?
@@ -733,7 +750,7 @@ ConvertFromInventor::convertIVTexToOSGTex(const SoNode* soNode,
}
// Set texture wrap mode
#ifdef COIN_BASIC_H
#ifdef __COIN__
if (soNode->isOfType(SoVRMLImageTexture::getClassTypeId())) {
// It looks like there is a high probability of bug in Coin (investigated on version 2.4.6).
// action->getTextureWrap() returns correct value on SoTexture2 (SoTexture2::CLAMP = 0x2900,

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
#ifndef OSG_CONVERT_TO_INVENTOR_H
#define OSG_CONVERT_TO_INVENTOR_H
//
// ConvertToInventor converts OSG scene graph to Inventor or VRML 1 scene graph
//
// It requires OSG and Inventor compatible library, such as Coin,
// SGI Inventor , or TGS Inventor.
//
//
// Autor: PCJohn (peciva _at fit.vutbr.cz)
//
// License: public domain
//
//
// THIS SOFTWARE IS NOT COPYRIGHTED
//
// This source code is offered for use in the public domain.
// You may use, modify or distribute it freely.
//
// This source code is distributed in the hope that it will be useful but
// WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
// DISCLAIMED. This includes but is not limited to warranties of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// If you find the source code useful, authors will kindly welcome
// if you give them credit and keep their names with their source code,
// but you are not forced to do so.
//
#include <stack>
#include <osg/CullFace>
#include <osg/FrontFace>
class SoSeparator;
namespace osg {
class BlendFunc;
class CullFace;
class FrontFace;
class Material;
class ShapeDrawable;
class TexEnv;
class TexGen;
};
class ConvertToInventor : public osg::NodeVisitor
{
public:
ConvertToInventor();
virtual ~ConvertToInventor();
SoNode* getIvSceneGraph() const;
void setVRML1Conversion(bool useVRML1) { vrml1Conversion = useVRML1; };
virtual void apply(osg::Node &node);
virtual void apply(osg::Geode &node);
virtual void apply(osg::Group &node);
#if 0
virtual void apply(Billboard& node) { apply((Geode&)node); }
virtual void apply(ProxyNode& node) { apply((Group&)node); }
virtual void apply(Projection& node) { apply((Group&)node); }
virtual void apply(CoordinateSystemNode& node) { apply((Group&)node); }
virtual void apply(ClipNode& node) { apply((Group&)node); }
virtual void apply(TexGenNode& node) { apply((Group&)node); }
virtual void apply(LightSource& node) { apply((Group&)node); }
#endif
//virtual void apply(Transform& node);
//virtual void apply(Camera& node) { apply((Transform&)node); }
//virtual void apply(CameraView& node) { apply((Transform&)node); }
virtual void apply(osg::MatrixTransform& node);
virtual void apply(osg::PositionAttitudeTransform& node);
#if 0
virtual void apply(Switch& node) { apply((Group&)node); }
virtual void apply(Sequence& node) { apply((Group&)node); }
virtual void apply(LOD& node) { apply((Group&)node); }
virtual void apply(PagedLOD& node) { apply((LOD&)node); }
virtual void apply(ClearNode& node) { apply((Group&)node); }
virtual void apply(OccluderNode& node) { apply((Group&)node); }
#endif
protected:
bool vrml1Conversion;
bool useIvExtensions;
SoSeparator *ivRoot;
typedef struct InventorState {
class SoSeparator *ivSeparator;
class SoTexture2 *ivTexture;
class SoNode *ivMaterial;
const osg::Material *osgMaterial;
bool osgTexture2Enabled;
const osg::Texture *osgTexture;
const osg::TexEnv *osgTexEnv;
bool osgTexGenS, osgTexGenT;
const osg::TexGen *osgTexGen;
bool osgLighting;
bool osgTwoSided;
osg::FrontFace::Mode osgFrontFace;
bool osgCullFaceEnabled;
osg::CullFace::Mode osgCullFace;
bool osgBlendEnabled;
const osg::BlendFunc *osgBlendFunc;
InventorState() {}
InventorState(SoSeparator *separator) : ivSeparator(separator), ivTexture(NULL),
ivMaterial(NULL), osgMaterial(NULL),
osgTexture2Enabled(false), osgTexture(NULL), osgTexEnv(NULL),
osgTexGenS(false), osgTexGenT(false), osgTexGen(NULL),
osgLighting(true), osgTwoSided(false), osgFrontFace(osg::FrontFace::COUNTER_CLOCKWISE),
osgCullFaceEnabled(false), osgCullFace(osg::CullFace::BACK),
osgBlendEnabled(false), osgBlendFunc(NULL) {}
InventorState(const InventorState &s) : ivSeparator(s.ivSeparator), ivTexture(s.ivTexture),
ivMaterial(s.ivMaterial), osgMaterial(s.osgMaterial),
osgTexture2Enabled(s.osgTexture2Enabled), osgTexture(s.osgTexture), osgTexEnv(s.osgTexEnv),
osgTexGenS(s.osgTexGenS), osgTexGenT(s.osgTexGenT), osgTexGen(osgTexGen),
osgLighting(s.osgLighting), osgTwoSided(s.osgTwoSided), osgFrontFace(s.osgFrontFace),
osgCullFaceEnabled(s.osgCullFaceEnabled), osgCullFace(s.osgCullFace),
osgBlendEnabled(s.osgBlendEnabled), osgBlendFunc(s.osgBlendFunc) {}
static InventorState createTopLevelState(SoSeparator *ivRoot) { return InventorState(ivRoot); }
};
std::stack<InventorState> ivStack;
typedef std::map<const class osg::TexEnv*, class SoTexture2*> Env2ivTexMap;
std::map<const osg::Texture*, Env2ivTexMap> ivTexturesMap;
int uniqueIdGenerator;
void processGeometry(const osg::Geometry *g, InventorState *ivState);
void processShapeDrawable(const osg::ShapeDrawable *d, InventorState *ivState);
virtual InventorState* createInventorState(const osg::StateSet *ss);
virtual void popInventorState();
};
#endif /* OSG_CONVERT_TO_INVENTOR_H */

View File

@@ -1,17 +1,27 @@
########################################################
# #
# Inventor plugin #
# Supported file formats (import only): #
# #
# Supported import formats: #
# - iv (ascii, binary) file format #
# - vrml 1.0 #
# - vrml 2.0 (when using Coin) #
# - VRML 1.0 #
# - VRML 2.0 (when using Coin) #
# #
# Supported export formats: #
# - iv format #
# - VRML 1.0 #
# #
########################################################
The plugin requires one of Inventor libraries:
- Coin (http://www.coin3d.org) - GPL, support of VRML 2.0
- Coin - GPL, support of VRML 2.0
(http://www.coin3d.org)
- SGI Inventor - LGPL
(http://oss.sgi.com/projects/inventor/)
- TGS Inventor - commercial
(http://www.tgs.com/)
Contributors:

View File

@@ -10,6 +10,8 @@
#include <Inventor/SoInteraction.h>
#include <Inventor/nodekits/SoNodeKit.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/actions/SoWriteAction.h>
#include <Inventor/actions/SoCallbackAction.h>
#ifdef COIN_BASIC_H
#include <Inventor/VRMLnodes/SoVRMLImageTexture.h>
@@ -17,6 +19,8 @@
#include "ConvertFromInventor.h"
#include "GroupSoLOD.h"
#include "ConvertToInventor.h"
// Register with Registry to instantiate the inventor reader.
REGISTER_OSGPLUGIN(Inventor, ReaderWriterIV)
@@ -81,3 +85,46 @@ ReaderWriterIV::readNode(const std::string& file,
return ReadResult::FILE_NOT_HANDLED;
}
osgDB::ReaderWriter::WriteResult
ReaderWriterIV::writeNode(const osg::Node& node, const std::string& fileName,
const osgDB::ReaderWriter::Options* options) const
{
// accept extension
std::string ext = osgDB::getLowerCaseFileExtension(fileName);
if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
bool useVRML1 = !isInventorExtension(osgDB::getFileExtension(fileName));
osg::notify(osg::INFO) << "osgDB::ReaderWriterIV::writeNode() Writing file "
<< fileName.data() << std::endl;
// Initialize Inventor
SoInteraction::init();
// Convert OSG graph to Inventor graph
ConvertToInventor osg2iv;
osg2iv.setVRML1Conversion(useVRML1);
(const_cast<osg::Node*>(&node))->accept(osg2iv);
SoNode *ivRoot = osg2iv.getIvSceneGraph();
if (ivRoot == NULL)
return WriteResult::ERROR_IN_WRITING_FILE;
ivRoot->ref();
// Change prefix according to VRML spec:
// Node names must not begin with a digit, and must not contain spaces or
// control characters, single or double quote characters, backslashes, curly braces,
// the sharp (#) character, the plus (+) character or the period character.
if (useVRML1)
SoBase::setInstancePrefix("_");
// Write Inventor graph to file
SoOutput out;
out.setHeaderString((useVRML1) ? "#VRML V1.0 ascii" : "#Inventor V2.1 ascii");
if (!out.openFile(fileName.c_str()))
return WriteResult::ERROR_IN_WRITING_FILE;
SoWriteAction wa(&out);
wa.apply(ivRoot);
ivRoot->unref();
return WriteResult::FILE_SAVED;
}

View File

@@ -11,18 +11,25 @@ class ReaderWriterIV : public osgDB::ReaderWriter
virtual const char* className() const
{
return "Inventor Reader";
return "Inventor reader/writer";
}
bool isInventorExtension(const std::string& extension) const
{
return osgDB::equalCaseInsensitive(extension, "iv") ? true : false;
}
virtual bool acceptsExtension(const std::string& extension) const
{
return osgDB::equalCaseInsensitive(extension, "iv") ? true :
return isInventorExtension(extension) ? true :
osgDB::equalCaseInsensitive(extension, "wrl") ? true : false;
}
virtual ReadResult readNode(const std::string& filename,
const osgDB::ReaderWriter::Options *) const;
virtual WriteResult writeNode(const osg::Node& node, const std::string& filename,
const osgDB::ReaderWriter::Options* options = NULL) const;
};
#endif