From Jan Peciva,

"I was working on a new version of Inventor plugin.
It was inspired by the need to get correct and high quality conversion,
so I verified the plugin on complex models and made number of serious fixes:

- the geometry is not two times on the output file (!)
- SoVRMLImageTexture: VRML texture support was rewritten according to
  Inventor programming practices, since it does not worked correctly on
  many models (Anyway, thanks for Gerrick Bivins to introduce it.)
- osg::ref wrong usage related crash fixed
- code cleaning and texture code overhaul
- LOD fixes
- appended README.txt with all the contributors I was able to get from
  SVN logs"
This commit is contained in:
Robert Osfield 2007-04-24 13:12:40 +00:00
parent 56188dde68
commit d35d8d0fa8
4 changed files with 209 additions and 359 deletions

View File

@ -35,12 +35,11 @@
#include <Inventor/nodes/SoPendulum.h>
#include <Inventor/nodes/SoShuttle.h>
#include <Inventor/nodes/SoLOD.h>
#include <Inventor/nodes/SoTexture2.h>
#include <Inventor/VRMLnodes/SoVRMLImageTexture.h>
#include <Inventor/misc/SoChildList.h>
#include <Inventor/SoPrimitiveVertex.h>
#include <Inventor/SbLinear.h>
#ifdef USE_COIN
#include <Inventor/SbImage.h>
#endif
#include "GroupSoLOD.h"
@ -58,7 +57,6 @@
ConvertFromInventor::ConvertFromInventor()
{
numPrimitives = 0;
_hasVRMLImageTexture = false;
}
///////////////////////////////////////////
ConvertFromInventor::~ConvertFromInventor()
@ -69,7 +67,7 @@ osg::Node* ConvertFromInventor::convert(SoNode* rootIVNode)
{
// Transformation matrix for converting Inventor coordinate system to OSG
// coordinate system
osg::Matrix ivToOSGMat(osg::Matrix(1.0, 0.0, 0.0, 0.0,
osg::Matrix ivToOSGMat(osg::Matrix(1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0,-1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0));
@ -85,12 +83,16 @@ osg::Node* ConvertFromInventor::convert(SoNode* rootIVNode)
// Create callback actions for the inventor nodes
// These callback functions perform the conversion
// note: if one class is derived from the other and both callbacks
// are registered, both functions will be called
SoCallbackAction cbAction;
cbAction.addPreCallback(SoShape::getClassTypeId(), preShape, this);
cbAction.addPostCallback(SoShape::getClassTypeId(), postShape, this);
cbAction.addPreCallback(SoGroup::getClassTypeId(), preGroup, this);
cbAction.addPostCallback(SoGroup::getClassTypeId(), postGroup, this);
cbAction.addPreCallback(SoTexture2::getClassTypeId(), preTexture, this);
cbAction.addPreCallback(SoVRMLImageTexture::getClassTypeId(),
preVRMLImageTexture, this);
cbAction.addPreCallback(SoLight::getClassTypeId(), preLight, this);
cbAction.addPreCallback(SoRotor::getClassTypeId(), preRotor, this);
cbAction.addPreCallback(SoPendulum::getClassTypeId(), prePendulum, this);
@ -98,48 +100,31 @@ osg::Node* ConvertFromInventor::convert(SoNode* rootIVNode)
cbAction.addTriangleCallback(SoShape::getClassTypeId(), addTriangleCB, this);
cbAction.addLineSegmentCallback(SoShape::getClassTypeId(), addLineSegmentCB,
this);
cbAction.addPointCallback(SoShape::getClassTypeId(), addPointCB, this);
#ifdef USE_COIN
//callback for VRMLImageTextures
cbAction.addPreCallback(SoVRMLImageTexture::getClassTypeId(),
_vrmlImageTextureAction,this);
#endif
// Traverse the inventor scene graph
cbAction.apply(rootIVNode);
// Pop the root osg node
groupStack.pop();
// Pop all the groups that are Transforms
// Verify that the last transform is _root .
assert(groupStack.size() > 0 && "groupStack underflow.");
osg::ref_ptr<osg::Group> group = groupStack.top();
while (strcmp(group->className(), "MatrixTransform") == 0)
{
groupStack.pop();
if (groupStack.empty()) break;
group = groupStack.top();
}
assert(group.get() == _root.get() && "groupStack error");
assert(groupStack.size() == 0 && "groupStack is not empty after traversal.");
assert(soTexStack.size() == 0 && "soTexStack was left at inconsistent state.");
assert(lightStack.size() == 1 && "lightStack was left at inconsistent state.");
lightStack.pop();
return _root.get();
}
#ifdef USE_COIN
//////////////////////////////////////////////////////////////////////////////////
SoCallbackAction::Response
ConvertFromInventor::_vrmlImageTextureAction(void* data, SoCallbackAction* action,
const SoNode* node)
{
#ifdef DEBUG_IV_PLUGIN
osg::notify(osg::INFO) << "_vrmlImageTextureAction() "
<< node->getTypeId().getName().getString() << std::endl;
#endif
///The converter data
ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
SoVRMLImageTexture* vit = (SoVRMLImageTexture*)(node);
if(vit)
{
//convert the SoVRMLImageTexture to an osg::Texture
thisPtr->_setVRMLImageTexture(vit,action);
}
return SoCallbackAction::CONTINUE;
}
#endif
///////////////////////////////////////////////////////////////////
SoCallbackAction::Response
ConvertFromInventor::preShape(void* data, SoCallbackAction* action,
@ -316,31 +301,15 @@ ConvertFromInventor::postShape(void* data, SoCallbackAction* action,
geometry->setColorBinding(thisPtr->colorBinding);
#if 0 // original code
// BUG: if default texture coordinates are used in Inventor model,
// the texture is not shown in OSG
if (!(thisPtr->textureCoords.empty()) && action->getNumTextureCoordinates()>0)
{
osg::notify(osg::NOTICE)<<"tex coords found"<<std::endl;
#elif 0 // bug fix
if (!(thisPtr->textureCoords.empty())/* && action->getNumTextureCoordinates()>0*/) // BUG: That was avoiding using of automatic texture coordinate generation of IV.
#else // improved code
if (thisPtr->textureCoords.empty())
osg::notify(osg::NOTICE)<<"tex coords not found"<<std::endl;
osg::notify(osg::INFO)<<"tex coords not found"<<std::endl;
else {
// report texture coordinate conditions
if (action->getNumTextureCoordinates()>0)
osg::notify(osg::DEBUG_INFO)<<"tex coords found"<<std::endl;
osg::notify(osg::INFO)<<"tex coords found"<<std::endl;
else
osg::notify(osg::DEBUG_INFO)<<"tex coords generated"<<std::endl;
#endif // end of changes
osg::notify(osg::INFO)<<"tex coords generated"<<std::endl;
// Get the texture transformation matrix
osg::Matrix textureMat;
@ -392,7 +361,7 @@ ConvertFromInventor::postShape(void* data, SoCallbackAction* action,
}
///////////////////////////////////////////////////////////////
SoCallbackAction::Response
ConvertFromInventor::preTexture(void* data, SoCallbackAction *,
ConvertFromInventor::preTexture(void* data, SoCallbackAction *,
const SoNode* node)
{
#ifdef DEBUG_IV_PLUGIN
@ -403,11 +372,29 @@ ConvertFromInventor::preTexture(void* data, SoCallbackAction *,
ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
if (thisPtr->soTexStack.size())
thisPtr->soTexStack.pop() ;
thisPtr->soTexStack.push((SoTexture2 *)node) ;
thisPtr->soTexStack.pop();
thisPtr->soTexStack.push(node);
return SoCallbackAction::CONTINUE;
}
//////////////////////////////////////////////////////////////////////////////////
SoCallbackAction::Response
ConvertFromInventor::preVRMLImageTexture(void* data, SoCallbackAction* action,
const SoNode* node)
{
#ifdef DEBUG_IV_PLUGIN
osg::notify(osg::INFO) << "preVRMLImageTexture() "
<< node->getTypeId().getName().getString() << std::endl;
#endif
ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
if (thisPtr->soTexStack.size())
thisPtr->soTexStack.pop();
thisPtr->soTexStack.push(node);
return SoCallbackAction::CONTINUE;
}
//////////////////////////////////////////////////////////////////
void ConvertFromInventor::transformLight(SoCallbackAction* action,
const SbVec3f& vec,
@ -497,7 +484,8 @@ ConvertFromInventor::preLight(void* data, SoCallbackAction* action,
return SoCallbackAction::CONTINUE;
}
///////////////////////////////////////////////////////////////////////////////////////
osg::ref_ptr<osg::StateSet> ConvertFromInventor::getStateSet(SoCallbackAction* action)
osg::ref_ptr<osg::StateSet>
ConvertFromInventor::getStateSet(SoCallbackAction* action)
{
osg::ref_ptr<osg::StateSet> stateSet = new osg::StateSet;
@ -629,47 +617,10 @@ ConvertFromInventor::preLight(void* data, SoCallbackAction* action,
// Convert the IV texture to OSG texture if any
osg::ref_ptr<osg::Texture2D> texture;
#ifdef USE_COIN
if(_hasVRMLImageTexture)
{
///VRMLImageTexture
texture = _getConvertedVRMLImageTexture();
_hasVRMLImageTexture = false;
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 USE_COIN
// This check is a very crude Coin detector.
// SGI's Inventor does not have REPLACE mode, but the Coin 3D library does.
case SoTexture2::REPLACE:
texEnv->setMode(osg::TexEnv::REPLACE);
break;
#endif
}
stateSet->setTextureAttributeAndModes(0,texEnv.get(),osg::StateAttribute::ON);
stateSet->setAttributeAndModes(new osg::ShadeModel());
}
else
#endif
if (soTexStack.top())
{
osg::notify(osg::NOTICE)<<"Have texture"<<std::endl;
//osg::ref_ptr<osg::Texture2D> tex;
osg::notify(osg::INFO)<<"Have texture"<<std::endl;
// Found a corresponding OSG texture object
if (ivToOsgTexMap[soTexStack.top()])
texture = ivToOsgTexMap[soTexStack.top()];
@ -698,9 +649,9 @@ ConvertFromInventor::preLight(void* data, SoCallbackAction* action,
texEnv->setMode(osg::TexEnv::BLEND);
break;
#ifdef USE_COIN
// This check is a very crude Coin detector.
#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;
@ -708,127 +659,61 @@ ConvertFromInventor::preLight(void* data, SoCallbackAction* action,
}
stateSet->setTextureAttributeAndModes(0,texEnv.get(),osg::StateAttribute::ON);
}
else
{
// fallback because many inventor models don't appear to have any SoTexture2..
SbVec2s soTexSize;
int soTexNC;
const unsigned char* texImage = action->getTextureImage(soTexSize, soTexNC);
if (texImage)
{
osg::notify(osg::NOTICE)<<"Image data found soTexSize[0]="<<soTexSize[0]<<", soTexSize[1]="<<soTexSize[1]<<"\tsoTexNC="<<soTexNC<<std::endl;
// Allocate memory for image data
unsigned char* imageData = new unsigned char[soTexSize[0] * soTexSize[1] *
soTexNC];
// Copy the texture image data from the inventor texture
memcpy(imageData, texImage, soTexSize[0] * soTexSize[1] * soTexNC);
// Create the osg image
osg::ref_ptr<osg::Image> osgTexImage = new osg::Image;
#if 0
SbString iv_string;
soTex->filename.get(iv_string);
std::string str(iv_string.getString());
osg::notify(osg::INFO) << str << " -> ";
if (str[0]=='\"') str.erase(str.begin());
if (str[str.size()-1]=='\"') str.erase(str.begin()+str.size()-1);
osg::notify(osg::INFO) << str << std::endl;
osgTexImage->setFileName(str);
#endif
GLenum formats[] = {GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA};
osgTexImage->setImage(soTexSize[0], soTexSize[1], 0, soTexNC,
formats[soTexNC-1], GL_UNSIGNED_BYTE, imageData,
osg::Image::USE_NEW_DELETE/*, -1*/); // BUG: -1 have to be removed (definitely WRONG packing!) It causes crashes of GLU.
// Create the osg texture
texture = new osg::Texture2D;
texture->setImage(osgTexImage.get());
static std::map<SoTexture2::Wrap, osg::Texture2D::WrapMode> texWrapMap2;
static bool firstTime2 = true;
if (firstTime2)
{
texWrapMap2[SoTexture2::CLAMP] = osg::Texture2D::CLAMP;
texWrapMap2[SoTexture2::REPEAT] = osg::Texture2D::REPEAT;
firstTime2 = false;
}
// Set texture wrap mode
texture->setWrap(osg::Texture2D::WRAP_S,texWrapMap2[action->getTextureWrapS()]);
texture->setWrap(osg::Texture2D::WRAP_T,texWrapMap2[action->getTextureWrapT()]);
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 USE_COIN
// This check is a very crude Coin detector.
// SGI's Inventor does not have REPLACE mode, but the Coin 3D library does.
case SoTexture2::REPLACE:
texEnv->setMode(osg::TexEnv::REPLACE);
break;
#endif
}
stateSet->setTextureAttributeAndModes(0,texEnv.get(),osg::StateAttribute::ON);
}
}
return stateSet;
}
////////////////////////////////////////////////////////////////////
osg::Texture2D*
ConvertFromInventor::convertIVTexToOSGTex(SoTexture2* soTex,
osg::Texture2D*
ConvertFromInventor::convertIVTexToOSGTex(const SoNode* soNode,
SoCallbackAction* action)
{
osg::notify(osg::NOTICE)<<"convertIVTexToOSGTex"<<std::endl;
osg::notify(osg::INFO)<<"convertIVTexToOSGTex of type "<<
soNode->getTypeId().getName().getString()<<std::endl;
SbVec2s soSize;
int soNC;
SbVec2s soTexSize;
int soTexNC;
// Get the texture size and components
const unsigned char* texImage;
texImage = soTex->image.getValue(soTexSize, soTexNC);
if (!texImage)
const unsigned char* soImageData = action->getTextureImage(soSize, soNC);
if (!soImageData) {
osg::notify(osg::WARN) << "IV import warning: Error while loading texture data." << std::endl;
return NULL;
}
// Allocate memory for image data
unsigned char* imageData = new unsigned char[soTexSize[0] * soTexSize[1] *
soTexNC];
unsigned char* osgImageData = new unsigned char[soSize[0] * soSize[1] * soNC];
// Copy the texture image data from the inventor texture
memcpy(imageData, texImage, soTexSize[0] * soTexSize[1] * soTexNC);
memcpy(osgImageData, soImageData, soSize[0] * soSize[1] * soNC);
// Create the osg image
osg::ref_ptr<osg::Image> osgTexImage = new osg::Image;
SbString iv_string;
soTex->filename.get(iv_string);
std::string str(iv_string.getString());
osg::notify(osg::INFO) << str << " -> ";
if (str[0]=='\"') str.erase(str.begin());
if (str[str.size()-1]=='\"') str.erase(str.begin()+str.size()-1);
osg::notify(osg::INFO) << str << std::endl;
osgTexImage->setFileName(str);
// File name
std::string fileName;
if (soNode->isOfType(SoTexture2::getClassTypeId()))
fileName = ((SoTexture2*)soNode)->filename.getValue().getString();
else
if (soNode->isOfType(SoVRMLImageTexture::getClassTypeId()))
fileName = ((SoVRMLImageTexture*)soNode)->url.getNum() >= 1 ?
((SoVRMLImageTexture*)soNode)->url.getValues(0)[0].getString() : "";
else
osg::notify(osg::WARN) << "IV import warning: Unsupported texture type: "
<< soNode->getTypeId().getName().getString() << std::endl;
osg::notify(osg::INFO) << fileName << " -> ";
if (fileName[0]=='\"') fileName.erase(fileName.begin());
if (fileName.size() > 0 && fileName[fileName.size()-1]=='\"')
fileName.erase(fileName.begin()+fileName.size()-1);
osg::notify(osg::INFO) << fileName << std::endl;
// Create the osg::Image
osg::ref_ptr<osg::Image> osgImage = new osg::Image;
osgImage->setFileName(fileName);
GLenum formats[] = {GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA};
osgTexImage->setImage(soTexSize[0], soTexSize[1], 0, soTexNC,
formats[soTexNC-1], GL_UNSIGNED_BYTE, imageData,
osg::Image::USE_NEW_DELETE/*, -1*/); // BUG: -1 have to be removed (definitely WRONG packing!) It causes crashes of GLU.
osgImage->setImage(soSize[0], soSize[1], 0, soNC, formats[soNC-1],
GL_UNSIGNED_BYTE, osgImageData, osg::Image::USE_NEW_DELETE);
// Create the osg texture
osg::ref_ptr<osg::Texture2D> osgTex = new osg::Texture2D;
osgTex->setImage(osgTexImage.get());
// Create the osg::Texture2D
osg::Texture2D *osgTex = new osg::Texture2D;
osgTex->setImage(osgImage.get());
static std::map<SoTexture2::Wrap, osg::Texture2D::WrapMode> texWrapMap;
static bool firstTime = true;
@ -840,14 +725,28 @@ ConvertFromInventor::convertIVTexToOSGTex(SoTexture2* soTex,
}
// Set texture wrap mode
osgTex->setWrap(osg::Texture2D::WRAP_S,texWrapMap[action->getTextureWrapS()]);
osgTex->setWrap(osg::Texture2D::WRAP_T,texWrapMap[action->getTextureWrapT()]);
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,
// and REPEAT = 0x2901), but SoVRMLImageTexture returns incorrect value of
// SoGLImage::REPEAT = 0, CLAMP = 1, CLAMP_TO_EDGE = 2).
// So, let's not use action and try to get correct value directly from texture node.
// PCJohn-2007-04-22
osgTex->setWrap(osg::Texture2D::WRAP_S, ((SoVRMLImageTexture*)soNode)->repeatS.getValue() ?
osg::Texture2D::REPEAT : osg::Texture2D::CLAMP_TO_EDGE);
osgTex->setWrap(osg::Texture2D::WRAP_T, ((SoVRMLImageTexture*)soNode)->repeatT.getValue() ?
osg::Texture2D::REPEAT : osg::Texture2D::CLAMP_TO_EDGE);
} else {
// Proper way to determine wrap mode
osgTex->setWrap(osg::Texture2D::WRAP_S, texWrapMap[action->getTextureWrapS()]);
osgTex->setWrap(osg::Texture2D::WRAP_T, texWrapMap[action->getTextureWrapT()]);
}
return osgTex.get();
return osgTex;
}
///////////////////////////////////////////////////////////////////
SoCallbackAction::Response
ConvertFromInventor::preGroup(void* data, SoCallbackAction* action,
ConvertFromInventor::preGroup(void* data, SoCallbackAction*,
const SoNode* node)
{
#ifdef DEBUG_IV_PLUGIN
@ -857,12 +756,12 @@ ConvertFromInventor::preGroup(void* data, SoCallbackAction* action,
ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
// Handle SoLOD nodes
if (node->getTypeId() == GroupSoLOD::getClassTypeId())
return preLOD(data, action, node);
// Create a new group and add it to the stack
osg::ref_ptr<osg::Group> group = new osg::Group;
// Create a new Group or LOD and add it to the stack
osg::ref_ptr<osg::Group> group;
if (node->isOfType(SoLOD::getClassTypeId()))
group = new osg::LOD;
else
group = new osg::Group;
thisPtr->groupStack.top()->addChild(group.get());
thisPtr->groupStack.push(group.get());
@ -883,9 +782,13 @@ ConvertFromInventor::preGroup(void* data, SoCallbackAction* action,
}
//////////////////////////////////////////////////////////////
SoCallbackAction::Response
ConvertFromInventor::postGroup(void* data, SoCallbackAction *,
ConvertFromInventor::postGroup(void* data, SoCallbackAction* action,
const SoNode* node)
{
// Handle SoLOD nodes specially
if (node->isOfType(SoLOD::getClassTypeId()))
return postLOD(data, action, node);
#ifdef DEBUG_IV_PLUGIN
osg::notify(osg::INFO) << "postGroup() "
<< node->getTypeId().getName().getString() << std::endl;
@ -893,19 +796,16 @@ ConvertFromInventor::postGroup(void* data, SoCallbackAction *,
ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
// Pop all the groups that are Transforms and add it
// to the corresponding parent group
// Pop all the groups that are Transforms
osg::ref_ptr<osg::Group> group = thisPtr->groupStack.top();
while (strcmp(group->className(), "MatrixTransform") == 0)
{
thisPtr->groupStack.pop();
thisPtr->groupStack.top()->addChild(group.get());
group = thisPtr->groupStack.top();
}
// Pop the group from the stack and add it to it's parent
// Pop the group from the stack
thisPtr->groupStack.pop();
thisPtr->groupStack.top()->addChild(group.get());
// Pop the state if the group is a Separator
if (node->isOfType(SoSeparator::getClassTypeId()))
@ -918,36 +818,50 @@ ConvertFromInventor::postGroup(void* data, SoCallbackAction *,
}
////////////////////////////////////////////////////////////
SoCallbackAction::Response
ConvertFromInventor::preLOD(void* data, SoCallbackAction *,
const SoNode* node)
ConvertFromInventor::postLOD(void* data, SoCallbackAction *,
const SoNode* node)
{
#ifdef DEBUG_IV_PLUGIN
osg::notify(osg::INFO) << "preLOD() "
osg::notify(osg::INFO) << "postLOD() "
<< node->getTypeId().getName().getString() << std::endl;
#endif
ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
// Inventor LOD node
// Inventor and OSG LOD node
SoLOD *ivLOD = (SoLOD *) node;
// Create a new LOD and add it to the stack
osg::ref_ptr<osg::LOD> lod = new osg::LOD;
thisPtr->groupStack.push(lod.get());
thisPtr->groupStack.top()->addChild(lod.get());
osg::LOD *lod = dynamic_cast<osg::LOD*>(thisPtr->groupStack.top());
// Get the center of LOD and set it
SbVec3f ivCenter = ivLOD->center.getValue();
lod->setCenter(osg::Vec3(ivCenter[0], ivCenter[1], ivCenter[2]));
// Verify the number of children and range values
int num = thisPtr->groupStack.top()->getNumChildren();
if (ivLOD->range.getNum()+1 != num && !(num == 0 && ivLOD->range.getNum() == 0)) {
osg::notify(osg::WARN) << "IV import warning: SoLOD does not "
<< "contain correct data in range field." << std::endl;
if (ivLOD->range.getNum()+1 < num) {
thisPtr->groupStack.top()->removeChildren(ivLOD->range.getNum() + 1,
num - ivLOD->range.getNum() - 1);
num = ivLOD->range.getNum() + 1;
}
}
// Get the ranges and set it
// lod->setRange(0, 0.0);
lod->setRange(0, 0.0, ivLOD->range[0]);
for (int i = 1; i < ivLOD->getChildren()->getLength(); i++)
lod->setRange(i, ivLOD->range[i-1], ivLOD->range[i]);
lod->setRange(ivLOD->getChildren()->getLength(),
ivLOD->range[ivLOD->getChildren()->getLength()],FLT_MAX);
if (num > 0) {
if (num == 1)
lod->setRange(0, 0.0, FLT_MAX);
else {
lod->setRange(0, 0.0, ivLOD->range[0]);
for (int i = 1; i < num-2; i++)
lod->setRange(i, ivLOD->range[i-1], ivLOD->range[i]);
lod->setRange(num-1, ivLOD->range[num-2], FLT_MAX);
}
}
// Pop the group from the stack
thisPtr->groupStack.pop();
return SoCallbackAction::CONTINUE;
}
@ -983,8 +897,8 @@ ConvertFromInventor::preRotor(void* data, SoCallbackAction *,
rotorTransform->setUpdateCallback(rotorCallback.get());
// Push the rotor transform onto the group stack
thisPtr->groupStack.push(rotorTransform.get());
thisPtr->groupStack.top()->addChild(rotorTransform.get());
thisPtr->groupStack.push(rotorTransform.get());
return SoCallbackAction::CONTINUE;
}
@ -1020,8 +934,8 @@ ConvertFromInventor::prePendulum(void* data, SoCallbackAction *,
pendulumTransform->setUpdateCallback(pendulumCallback);
// Push the pendulum transform onto the group stack
thisPtr->groupStack.push(pendulumTransform.get());
thisPtr->groupStack.top()->addChild(pendulumTransform.get());
thisPtr->groupStack.push(pendulumTransform.get());
return SoCallbackAction::CONTINUE;
}
@ -1056,8 +970,8 @@ ConvertFromInventor::preShuttle(void* data, SoCallbackAction *,
shuttleTransform->setUpdateCallback(shuttleCallback);
// Push the shuttle transform onto the group stack
thisPtr->groupStack.push(shuttleTransform.get());
thisPtr->groupStack.top()->addChild(shuttleTransform.get());
thisPtr->groupStack.push(shuttleTransform.get());
return SoCallbackAction::CONTINUE;
}
@ -1151,74 +1065,3 @@ void ConvertFromInventor::addPointCB(void* data, SoCallbackAction* action,
thisPtr->numPrimitives++;
thisPtr->primitiveType = osg::PrimitiveSet::POINTS;
}
#ifdef USE_COIN
//////////////////////////////////////////////////////////////////////
void ConvertFromInventor::_setVRMLImageTexture(const SoVRMLImageTexture* vit,
SoCallbackAction* /*action*/)
{
_hasVRMLImageTexture = true;
///Coin API to extract VRML97 ImageTexture
int nComponents = 1;
SbImage* vitImage = (SbImage*)vit->getImage();
SbString filename;
filename = vit->url.getValues(0)[0];
vitImage->readFile(filename);
SbVec2s dimensions;
dimensions[0] = 2;
dimensions[1] = 2;
const unsigned char* dataPtr = vitImage->getValue(dimensions,nComponents);
unsigned char* data = new unsigned char[dimensions[0]*
dimensions[1]*
nComponents];
///Is this effiecient???
memcpy(data, dataPtr, dimensions[0]*dimensions[1]*nComponents);
GLenum format = GL_RGBA;
switch (nComponents)
{
case 1:
format = GL_LUMINANCE;
break;
case 2:
format = GL_LUMINANCE_ALPHA;
break;
case 3:
format = GL_RGB;
break;
case 4:
default:
format = GL_RGBA;
break;
};
osg::ref_ptr<osg::Image> image = new osg::Image();
image->setImage(dimensions[0], dimensions[1], 1, nComponents,
format, GL_UNSIGNED_BYTE, const_cast<unsigned char*>(data),
osg::Image::USE_NEW_DELETE);
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D();
texture->setImage(image.get());
osg::Texture::WrapMode smode = (vit->repeatS.getValue())?(osg::Texture::REPEAT):(osg::Texture::CLAMP);
osg::Texture::WrapMode tmode = (vit->repeatT.getValue())?(osg::Texture::REPEAT):(osg::Texture::CLAMP);
// Set texture wrap mode
texture->setWrap(osg::Texture2D::WRAP_S,smode);
texture->setWrap(osg::Texture2D::WRAP_T,tmode);
_currentVRMLImageTexture = texture;
_currentVRMLImageTexture->dirtyTextureObject();
}
////////////////////////////////////////////////////////////////////
osg::Texture2D* ConvertFromInventor::_getConvertedVRMLImageTexture()
{
if(_currentVRMLImageTexture.valid())
{
return _currentVRMLImageTexture.get();
}
return 0;
}
#endif

View File

@ -6,28 +6,18 @@
#include <osg/PrimitiveSet>
#include <osg/Texture2D>
#include <osg/Light>
#include <Inventor/actions/SoCallbackAction.h>
#ifdef COIN_SOCALLBACKACTION_H
#define USE_COIN 1
#endif
#ifdef USE_COIN
#include <Inventor/VRMLnodes/SoVRMLImageTexture.h>
#endif
#include <vector>
#include <stack>
class ConvertFromInventor
class ConvertFromInventor
{
public:
ConvertFromInventor();
~ConvertFromInventor();
osg::Node* convert(SoNode* rootIVNode);
osg::Node* convert(SoNode* rootIVNode);
private:
// Callback functions for converting inventor scene graph to osg
@ -51,7 +41,13 @@ class ConvertFromInventor
SoCallbackAction* action, const SoNode* node);
static SoCallbackAction::Response preShuttle(void* data,
SoCallbackAction* action, const SoNode* node);
static SoCallbackAction::Response preLOD(void* data,
static SoCallbackAction::Response postLOD(void* data,
SoCallbackAction* action, const SoNode* node);
///Callback for VRMLImageTexture
///\param data The pointer to ConvertFromInventor object
///\param action The action handling class
///\param node The current VRMLImageTexture node
static SoCallbackAction::Response preVRMLImageTexture(void* data,
SoCallbackAction* action, const SoNode* node);
static void addTriangleCB(void* data, SoCallbackAction* action,
@ -63,41 +59,23 @@ class ConvertFromInventor
const SoPrimitiveVertex *v1);
static void addPointCB(void* data, SoCallbackAction* action,
const SoPrimitiveVertex *v0);
#ifdef USE_COIN
///Callback to intercept VRMLImageTexture(s)
///\param data The node data
///\param action The callback handling class
///\param node The current VRMLImageTexture node
static SoCallbackAction::Response
_vrmlImageTextureAction(void* data,
SoCallbackAction* action,
const SoNode* node);
///Set the SVRMLImageTexture for the current node
///\param texture The found texture
///\param action The callback action
void _setVRMLImageTexture(const SoVRMLImageTexture* texture,
SoCallbackAction* action);
///Get the currently converted texture
osg::Texture2D* _getConvertedVRMLImageTexture();
#endif
private:
void addVertex(SoCallbackAction* action, const SoPrimitiveVertex* v,
int index);
osg::ref_ptr<osg::StateSet> getStateSet(SoCallbackAction* action);
osg::ref_ptr<osg::StateSet> getStateSet(SoCallbackAction* action);
osg::Texture2D* convertIVTexToOSGTex(SoTexture2* soTex,
SoCallbackAction* action);
osg::Texture2D* convertIVTexToOSGTex(const SoNode* soNode,
SoCallbackAction* action);
void transformLight(SoCallbackAction* action, const SbVec3f& vec,
osg::Vec3& transVec);
// OSG doesn't seem to have a transpose function for matrices
void transposeMatrix(osg::Matrix& mat);
private:
// Normal and color binding
@ -121,11 +99,12 @@ class ConvertFromInventor
// Stack of group nodes (used to build the scene graph)
std::stack<osg::Group* > groupStack;
// Stack of texture nodes (used for attaching the right texture to the
// geosets)
std::stack<SoTexture2*> soTexStack;
// geosets). Supported types are SoTexture2 and SoVRMLImageTexture for now.
std::stack<const SoNode*> soTexStack;
// For avoiding duplication of same texture objects
std::map<SoTexture2*, osg::Texture2D*> ivToOsgTexMap;
// Mapping from SoTexture2 and SoVRMLImageTexture to already converted
// osg::Texture2D - avoids duplication of same texture objects
std::map<const SoNode*, osg::Texture2D*> ivToOsgTexMap;
// Stack to maintain the list of lights at each level of the
// scenegraph
@ -133,8 +112,6 @@ class ConvertFromInventor
std::stack<LightList> lightStack;
osg::ref_ptr<osg::MatrixTransform> _root;///<The root node;
bool _hasVRMLImageTexture;///<Flag for processing VRMLImamgeTextures
osg::ref_ptr<osg::Texture2D> _currentVRMLImageTexture;///<The current converted texture
};
#endif

View File

@ -0,0 +1,26 @@
########################################################
# Inventor plugin #
# Supported file formats (import only): #
# - iv (ascii, binary) file format #
# - vrml 1.0 #
# - vrml 2.0 (when using Coin) #
########################################################
The plugin requires one of Inventor libraries:
- Coin (http://www.coin3d.org) - GPL, support of VRML 2.0
- SGI Inventor - LGPL
- TGS Inventor - commercial
Contributors:
Sean Spicer - Vivek (c) Magic-Earth - Original author of the plugin
Gerrick Bivins
PCJohn - Jan Peciva, Cadwork (c)
Minor fixes:
Ruben
Eric Sokolosky
Martin Aumueller

View File

@ -10,6 +10,7 @@
#include <Inventor/SoInteraction.h>
#include <Inventor/nodekits/SoNodeKit.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/VRMLnodes/SoVRMLImageTexture.h>
#include "ConvertFromInventor.h"
#include "GroupSoLOD.h"
@ -44,6 +45,9 @@ ReaderWriterIV::readNode(const std::string& file,
// Initial GroupSoLOD node
GroupSoLOD::initClass();
// Disable delayed loading of VRML textures
SoVRMLImageTexture::setDelayFetchURL(FALSE);
// Open the file
SoInput input;
if (!input.openFile(fileName.data()))