Changeset 11032

Show
Ignore:
Timestamp:
01/31/10 13:55:29 (4 years ago)
Author:
robert
Message:

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"

Location:
OpenSceneGraph/trunk/src/osgPlugins/Inventor
Files:
2 removed
9 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/src/osgPlugins/Inventor/CMakeLists.txt

    r9339 r11032  
    44    ConvertToInventor.cpp 
    55    ConvertFromInventor.cpp 
    6     GroupSoLOD.cpp 
    76    PendulumCallback.cpp 
    87    ReaderWriterIV.cpp 
     
    1211    ConvertToInventor.h 
    1312    ConvertFromInventor.h 
    14     GroupSoLOD.h 
    1513    PendulumCallback.h 
    1614    ReaderWriterIV.h 
     
    2220INCLUDE_DIRECTORIES(${INVENTOR_INCLUDE_DIR}) 
    2321 
    24 SET(TARGET_LIBRARIES_VARS INVENTOR_LIBRARY) 
     22SET(TARGET_ADDED_LIBRARIES ${INVENTOR_LIBRARY}) 
    2523 
    2624SETUP_PLUGIN(iv iv) 
  • OpenSceneGraph/trunk/src/osgPlugins/Inventor/ConvertFromInventor.cpp

    r9585 r11032  
    2727#include <Inventor/SoInteraction.h> 
    2828#include <Inventor/nodes/SoSeparator.h> 
     29#include <Inventor/nodes/SoTransformSeparator.h> 
    2930#include <Inventor/nodes/SoShape.h> 
    3031#include <Inventor/nodes/SoVertexShape.h> 
     
    3839#include <Inventor/nodes/SoLOD.h> 
    3940#include <Inventor/nodes/SoTexture2.h> 
     41#include <Inventor/nodes/SoEnvironment.h> 
    4042#include <Inventor/misc/SoChildList.h> 
    4143#include <Inventor/SoPrimitiveVertex.h> 
     
    4345#include <Inventor/nodes/SoTransform.h> 
    4446#include <Inventor/nodes/SoInfo.h> 
     47#include <Inventor/actions/SoWriteAction.h> 
     48#include <Inventor/elements/SoModelMatrixElement.h> 
    4549 
    4650#ifdef __COIN__ 
     
    5155#endif 
    5256 
    53 #include "GroupSoLOD.h" 
     57#if defined(__COIN__) && (COIN_MAJOR_VERSION >= 3 || \ 
     58    (COIN_MAJOR_VERSION == 2 && COIN_MINOR_VERSION>=5)) 
     59#define INVENTOR_SHADERS_AVAILABLE 
     60#endif 
     61 
     62#ifdef INVENTOR_SHADERS_AVAILABLE 
     63#include <Inventor/nodes/SoShaderProgram.h> 
     64#include <Inventor/nodes/SoVertexShader.h> 
     65#include <Inventor/nodes/SoGeometryShader.h> 
     66#include <Inventor/nodes/SoFragmentShader.h> 
     67#endif 
    5468 
    5569#include <map> 
     
    6579 
    6680#define DEBUG_IV_PLUGIN 
     81#define NOTIFY_HEADER "Inventor Plugin (reader): " 
     82 
    6783/////////////////////////////////////////// 
    6884ConvertFromInventor::ConvertFromInventor() 
     
    7187    transformInfoName = ""; 
    7288    appearanceName = ""; 
    73     inAppearanceWithNoTexture = false; 
    74     lightGroup = NULL; 
    7589} 
    7690/////////////////////////////////////////// 
     
    7892{ 
    7993} 
     94/////////////////////////////////////////////////////////////////// 
     95static bool 
     96nodePreservesState(const SoNode *node) 
     97{ 
     98    return node->isOfType(SoSeparator::getClassTypeId()) || 
     99           (node->getChildren() != NULL && node->affectsState() == FALSE); 
     100} 
     101//////////////////////////////////////////////////////////////////// 
     102SoCallbackAction::Response 
     103ConvertFromInventor::restructure(void* data, SoCallbackAction* action, 
     104                                 const SoNode* node) 
     105{ 
     106#ifdef DEBUG_IV_PLUGIN 
     107    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "restructure() " 
     108              << node->getTypeId().getName().getString(); 
     109#endif 
     110 
     111    int childrenTotal = 0; 
     112    int numModifiedChildren = 0; 
     113    int numRemovedNodes = 0; 
     114    std::vector<std::vector<int> > &stack = *((std::vector<std::vector<int> >*)data); 
     115 
     116    if (node->isOfType(SoGroup::getClassTypeId())) { 
     117 
     118        SoGroup *group = (SoGroup*)node; 
     119        SoGroup *affectedScene = NULL; 
     120        childrenTotal = group->getNumChildren(); 
     121 
     122        for (int i=0, c=group->getNumChildren(); i<c; i++) { 
     123            SoNode *child = group->getChild(i); 
     124            if (!child->isOfType(SoSeparator::getClassTypeId()) && 
     125                child->affectsState()) { 
     126 
     127                // Put the node bellow separator 
     128                SoSeparator *s = new SoSeparator; 
     129                s->addChild(group->getChild(i)); 
     130                group->replaceChild(i, s); 
     131                numModifiedChildren++; 
     132 
     133                // Create the scene that may be affected by the node 
     134                if (!affectedScene) { 
     135 
     136                    // Create the graph of nodes that may be influenced 
     137                    // by the node 
     138                    const SoFullPath *path = (const SoFullPath*)action->getCurPath(); 
     139                    assert(path->getLength() == 0 || 
     140                           path->getNode(path->getLength()-1) == group && 
     141                           "Group being restructured is not at the end of the path."); 
     142                    int stackLevel = stack.size()-2; 
     143                    for (int j=path->getLength()-2; j>=0; j--, stackLevel--) { 
     144 
     145                        // Get the appropriate stack level of nodesToRemove 
     146                        assert(stackLevel >=0); 
     147                        std::vector<int> &nodesToRemove = stack[stackLevel]; 
     148 
     149                        // Get parent and index of the current group 
     150                        SoNode *parent = path->getNode(j); 
     151                        int childIndex = path->getIndex(j+1); 
     152                        const SoChildList *chl = parent->getChildren(); 
     153                        assert(chl->operator[](childIndex) == path->getNode(j+1) && 
     154                               "Wrong indexing."); 
     155 
     156                        // Create affected scene graph 
     157                        if (!affectedScene) 
     158                            affectedScene = new SoGroup; 
     159 
     160                        // Copy nodes to the graph 
     161                        for (int k=childIndex+1, n=chl->getLength(); k<n; k++) { 
     162                            affectedScene->addChild(chl->operator[](k)); 
     163                            nodesToRemove.push_back(k); 
     164                            numRemovedNodes++; 
     165                        } 
     166 
     167                        // Stop recursion if we reached separator 
     168                        // or other state-preserving node. 
     169                        if (nodePreservesState(parent)) 
     170                            break; 
     171                    } 
     172                } 
     173 
     174                // Append the affected graph to the separator 
     175                s->addChild(affectedScene); 
     176            } 
     177        } 
     178    } 
     179 
     180#ifdef DEBUG_IV_PLUGIN 
     181    if (numModifiedChildren == 0) 
     182        osg::notify(osg::DEBUG_INFO) << ": no changes necessary" << std::endl; 
     183    else 
     184        osg::notify(osg::DEBUG_INFO) << ": " << numModifiedChildren << 
     185                  " nodes of " << childrenTotal << " restruc., " << 
     186                  numRemovedNodes << " removed" << std::endl; 
     187#endif 
     188 
     189    return SoCallbackAction::CONTINUE; 
     190} 
    80191/////////////////////////////////////////////////////////// 
    81 osg::Node* ConvertFromInventor::convert(SoNode* rootIVNode) 
    82 {     
    83     // Transformation matrix for converting Inventor coordinate system to OSG  
     192SoCallbackAction::Response 
     193ConvertFromInventor::restructurePreNode(void* data, SoCallbackAction* action, 
     194                             const SoNode* node) 
     195{ 
     196    std::vector<std::vector<int> > &stack = *((std::vector<std::vector<int> >*)data); 
     197 
     198    stack.push_back(std::vector<int>()); 
     199 
     200    return SoCallbackAction::CONTINUE; 
     201} 
     202//////////////////////////////////////////////////////////////////// 
     203SoCallbackAction::Response 
     204ConvertFromInventor::restructurePostNode(void* data, SoCallbackAction* action, 
     205                              const SoNode* node) 
     206{ 
     207    std::vector<std::vector<int> > &stack = *((std::vector<std::vector<int> >*)data); 
     208 
     209    assert(stack.size() > 0 && "Stack is empty"); 
     210    std::vector<int> &nodesToRemove = stack.back(); 
     211 
     212    if (nodesToRemove.size() > 0) { 
     213 
     214#ifdef DEBUG_IV_PLUGIN 
     215        osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postNode()   " 
     216                  << node->getTypeId().getName().getString() 
     217                  << " (level " << stack.size() << ") removed " 
     218                  << nodesToRemove.size() << " node(s)" << std::endl; 
     219#endif 
     220 
     221        assert(node->getChildren()); 
     222        for (int i=nodesToRemove.size()-1; i>=0; i--) { 
     223            assert(i==0 || nodesToRemove[i-1] < nodesToRemove[i] && 
     224                   "Children to remove are not in order."); 
     225            node->getChildren()->remove(nodesToRemove[i]); 
     226        } 
     227    } 
     228 
     229    stack.pop_back(); 
     230 
     231    return SoCallbackAction::CONTINUE; 
     232} 
     233/////////////////////////////////////////////////////////////////// 
     234void 
     235ConvertFromInventor::preprocess(SoNode* root) 
     236{ 
     237#ifdef DEBUG_IV_PLUGIN 
     238    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "Preprocessing..." << std::endl; 
     239#endif 
     240 
     241    SoCallbackAction action; 
     242    std::vector<std::vector<int> > stackOfNodesToRemove; 
     243 
     244    // Callbacks for troublesome nodes 
     245    action.addPreCallback(SoNode::getClassTypeId(), 
     246                          restructurePreNode, &stackOfNodesToRemove); 
     247    action.addPostCallback(SoLOD::getClassTypeId(), 
     248                           restructure, &stackOfNodesToRemove); 
     249    action.addPostCallback(SoNode::getClassTypeId(), 
     250                           restructurePostNode, &stackOfNodesToRemove); 
     251 
     252    // Traverse the scene 
     253    action.apply(root); 
     254 
     255#if 0 // For debugging purposes: Write preprocessed scene to the file 
     256    SoOutput out; 
     257    out.openFile("preprocess.iv"); 
     258    SoWriteAction wa(&out); 
     259    wa.apply(root); 
     260#endif 
     261} 
     262/////////////////////////////////////////////////////////// 
     263osg::Node* 
     264ConvertFromInventor::convert(SoNode* ivRootNode) 
     265{ 
     266#ifdef DEBUG_IV_PLUGIN 
     267    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "Converting..." << std::endl; 
     268#endif 
     269 
     270    // Transformation matrix for converting Inventor coordinate system to OSG 
    84271    // coordinate system 
    85272    osg::Matrix ivToOSGMat(osg::Matrix(1.0, 0.0, 0.0, 0.0, 
     
    88275                                       0.0, 0.0, 0.0, 1.0)); 
    89276 
    90     // Create a root node and push it onto the stack 
    91     _root = new osg::MatrixTransform; 
    92     _root->setMatrix(ivToOSGMat); 
    93     groupStack.push(_root.get()); 
    94  
    95     // Push an empty list of light and push it onto the light stack 
    96     LightList lightList; 
    97     lightStack.push(lightList); 
    98      
    99     // Create callback actions for the inventor nodes  
     277    // Root of the scene 
     278    osg::ref_ptr<osg::Group> osgRootNode = new osg::MatrixTransform(ivToOSGMat); 
     279 
     280    // Initialize Inventor state stack 
     281    // (ivStateStack is used to track the state that is not accessible by 
     282    // SoCallbackAction functions) 
     283    ivStateStack.push(IvStateItem(ivRootNode, osgRootNode)); 
     284 
     285    // Create callback actions for the inventor nodes 
    100286    // These callback functions perform the conversion 
    101287    // note: if one class is derived from the other and both callbacks 
    102288    // are registered, both functions will be called 
    103289    SoCallbackAction cbAction; 
     290 
     291    // Node callbacks are used for detecting which node 
     292    // preserves state (like SoSeparator) and which not. 
     293    // There are few nodes that behave like SoSeparator although they 
     294    // are not derived from it. 
     295    // Note: postNode callback is moved down, because it must be 
     296    // called as the last callback. 
     297    cbAction.addPreCallback(SoNode::getClassTypeId(), preNode, this); 
     298 
     299    // SoTransformSeparator callbacks. Special handling of transformations. 
     300    cbAction.addPreCallback(SoTransformSeparator::getClassTypeId(), preTransformSeparator, this); 
     301    cbAction.addPostCallback(SoTransformSeparator::getClassTypeId(), postTransformSeparator, this); 
     302 
     303    // LOD (Level of Detail) callbacks. Handles SoLOD nodes. 
     304    // FIXME: SoLevelOfDetail needs to be implemented and tested. 
     305    cbAction.addPreCallback(SoLOD::getClassTypeId(), preLOD, this); 
     306    cbAction.addPostCallback(SoLOD::getClassTypeId(), postLOD, this); 
     307 
     308    // Shape callbacks collects all triangles and all the geometry data. 
     309    // Moreover, they handle transformations, ... 
    104310    cbAction.addPreCallback(SoShape::getClassTypeId(), preShape, this); 
    105311    cbAction.addPostCallback(SoShape::getClassTypeId(), postShape, this); 
    106     cbAction.addPreCallback(SoGroup::getClassTypeId(), preGroup, this); 
    107     cbAction.addPostCallback(SoGroup::getClassTypeId(), postGroup, this); 
    108     cbAction.addPreCallback(SoTexture2::getClassTypeId(), preTexture, this); 
     312 
     313    // Handling of textures 
     314    cbAction.addPostCallback(SoTexture2::getClassTypeId(), 
     315                            postTexture, this); 
    109316#ifdef __COIN__ 
    110     cbAction.addPreCallback(SoVRMLImageTexture::getClassTypeId(), 
    111                             preVRMLImageTexture, this); 
    112     cbAction.addPreCallback(SoVRMLAppearance::getClassTypeId(), 
    113                             preVRMLAppearance, this); 
     317    cbAction.addPostCallback(SoVRMLImageTexture::getClassTypeId(), 
     318                            postTexture, this); 
     319    cbAction.addPostCallback(SoVRMLAppearance::getClassTypeId(), 
     320                            postTexture, this); 
     321#endif 
     322 
     323#ifdef __COIN__ 
    114324    cbAction.addPreCallback(SoInfo::getClassTypeId(), preInfo, this); 
    115325#endif 
     326 
     327    // Lights 
    116328    cbAction.addPreCallback(SoLight::getClassTypeId(), preLight, this); 
     329 
     330    // Environment (ambient light,...) 
     331    cbAction.addPreCallback(SoEnvironment::getClassTypeId(), preEnvironment, this); 
     332 
     333    // Shaders 
     334#ifdef INVENTOR_SHADERS_AVAILABLE 
     335    cbAction.addPreCallback(SoShaderProgram::getClassTypeId(), preShaderProgram, this); 
     336#endif 
     337 
     338    // Motion callbacks 
    117339    cbAction.addPreCallback(SoRotor::getClassTypeId(), preRotor, this); 
    118340    cbAction.addPreCallback(SoPendulum::getClassTypeId(), prePendulum, this); 
    119341    cbAction.addPreCallback(SoShuttle::getClassTypeId(), preShuttle, this); 
     342 
     343    // Geometry callbacks 
    120344    cbAction.addTriangleCallback(SoShape::getClassTypeId(), addTriangleCB, this); 
    121345    cbAction.addLineSegmentCallback(SoShape::getClassTypeId(), addLineSegmentCB, 
     
    123347    cbAction.addPointCallback(SoShape::getClassTypeId(), addPointCB, this); 
    124348 
     349    // Post node callback 
     350    cbAction.addPostCallback(SoNode::getClassTypeId(), postNode, this); 
     351 
    125352    // Traverse the inventor scene graph 
    126     cbAction.apply(rootIVNode); 
    127  
    128     // Pop all the groups that are Transforms 
    129     // Verify that the last transform is _root . 
    130     assert(groupStack.size() > 0 && "groupStack underflow."); 
    131     osg::ref_ptr<osg::Group> group = groupStack.top(); 
    132     while (strcmp(group->className(), "MatrixTransform") == 0) 
    133     { 
    134         groupStack.pop(); 
    135         if (groupStack.empty()) break; 
    136         group = groupStack.top(); 
    137     } 
    138     assert(group.get() == _root.get() && "groupStack error"); 
    139     assert(groupStack.size() == 0 && "groupStack is not empty after traversal."); 
    140  
    141     assert(soTexStack.size() == 0 && "soTexStack was left at inconsistent state."); 
    142  
    143     assert(lightStack.size() == 1 && "lightStack was left at inconsistent state."); 
    144     lightStack.pop(); 
    145  
    146     return _root.get();  
     353    cbAction.apply(ivRootNode); 
     354 
     355    // Remove superfluous group 
     356    if (osgRootNode->getNumChildren() == 1) { 
     357        osg::ref_ptr<osg::Group> toRemove = osgRootNode->getChild(0)->asGroup(); 
     358        assert(toRemove.get() && 
     359               strcmp(toRemove->className(), "Group") == 0 && 
     360               "IvStateStack osg graph is expected to be " 
     361               "headed by osg::Group"); 
     362        osgRootNode->removeChild(0u); 
     363        for (int i=0, c=toRemove->getNumChildren(); i<c; i++) 
     364            osgRootNode->addChild(toRemove->getChild(i)); 
     365    } 
     366 
     367    return osgRootNode.get(); 
    147368} 
    148369/////////////////////////////////////////////////////////////////// 
    149 SoCallbackAction::Response  
    150 ConvertFromInventor::preShape(void* data, SoCallbackAction* action,  
     370static void 
     371notifyAboutMatrixContent(const osg::NotifySeverity level, const SbMatrix &m) 
     372{ 
     373    SbVec3f t,s; 
     374    SbRotation r,so; 
     375    m.getTransform(t, r, s, so); 
     376    SbVec3f axis; 
     377    float angle; 
     378    r.getValue(axis, angle); 
     379    osg::notify(level) << NOTIFY_HEADER << "  Translation: " << 
     380              t[0] << "," << t[1] << "," << t[2] << std::endl; 
     381    osg::notify(level) << NOTIFY_HEADER << "  Rotation: (" << 
     382              axis[0] << "," << axis[1] << "," << axis[2] << ")," << angle << std::endl; 
     383} 
     384/////////////////////////////////////////////////////////////////// 
     385void 
     386ConvertFromInventor::appendNode(osg::Node *n, const SoCallbackAction *action) 
     387{ 
     388    IvStateItem &ivState = ivStateStack.top(); 
     389    SbMatrix currentMatrix = action->getModelMatrix(); 
     390    SbMatrix inheritedMatrix = ivState.inheritedTransformation; 
     391 
     392    // Keep children order - this must be done for some nodes like 
     393    // SoSwitch, SoLOD,... 
     394    // We will append dummy nodes if the child is expected to be on 
     395    // higher index. 
     396    if (ivState.flags & IvStateItem::KEEP_CHILDREN_ORDER) { 
     397 
     398        // Determine child index 
     399        int childIndex = -1; 
     400        const SoFullPath *path = (const SoFullPath*)(((SoCallbackAction*)action)->getCurPath()); 
     401        for (int i=path->getLength()-2; i>=0; i--) 
     402            if (path->getNode(i) == ivState.keepChildrenOrderParent) { 
     403                childIndex = path->getIndex(i+1); 
     404                assert(ivState.keepChildrenOrderParent->getChildren()); 
     405                assert((ivState.keepChildrenOrderParent->getChildren()->operator[](childIndex) == path->getNode(i+1)) && "Indexing is wrong."); 
     406                break; 
     407            } 
     408        assert(childIndex != -1 && "Node did not found."); 
     409 
     410        // Append dummy nodes to keep children order 
     411        assert(int(ivState.osgStateRoot->getNumChildren()) <= childIndex && 
     412               "Number of children in ivState.osgStateRoot is too big."); 
     413        while (int(ivState.osgStateRoot->getNumChildren()) < childIndex) 
     414            ivState.osgStateRoot->addChild(new osg::Node); 
     415    } 
     416 
     417#ifdef DEBUG_IV_PLUGIN 
     418    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "appendNode: " 
     419              << n->className(); 
     420#endif 
     421 
     422    if (currentMatrix == inheritedMatrix) { 
     423 
     424        // just append node to the current group in osg scene graph 
     425        ivState.osgStateRoot->addChild(n); 
     426        ivState.lastUsedTransformation = inheritedMatrix; 
     427 
     428#ifdef DEBUG_IV_PLUGIN 
     429        if (osg::isNotifyEnabled(osg::DEBUG_INFO)) 
     430            osg::notify(osg::DEBUG_INFO) << 
     431                      " uses parent transformation" << std::endl; 
     432#endif 
     433 
     434    } else { 
     435 
     436        if (!(ivState.flags & IvStateItem::KEEP_CHILDREN_ORDER) && 
     437            currentMatrix == ivState.lastUsedTransformation) { 
     438 
     439            // Previous node has the same transformation. Let's use it. 
     440            assert(ivState.osgStateRoot->getNumChildren() != 0 && 
     441                   "This should never happen - there is no item on " 
     442                   "osgShapeGraphs list while want to use last one."); 
     443            osg::Transform *t = ivState.osgStateRoot->getChild(ivState.osgStateRoot->getNumChildren()-1)->asTransform(); 
     444            assert(t && "This should never happen - want to use " 
     445                        "transformation of previous scene geometry " 
     446                        "and it does not have Transform node."); 
     447            t->addChild(n); 
     448 
     449#ifdef DEBUG_IV_PLUGIN 
     450            if (osg::isNotifyEnabled(osg::DEBUG_INFO)) 
     451                osg::notify(osg::DEBUG_INFO) << 
     452                          " reuses previous transformation" << std::endl; 
     453#endif 
     454 
     455        } else { 
     456 
     457            // We need a new transformation node 
     458            osg::Matrix m(osg::Matrix(currentMatrix.operator float*())); 
     459            osg::Matrix m2; 
     460            m2.invert(osg::Matrix(inheritedMatrix.operator float*())); 
     461            m.postMult(m2); 
     462            osg::MatrixTransform *mt = new osg::MatrixTransform(m); 
     463            mt->addChild(n); 
     464 
     465            ivState.osgStateRoot->addChild(mt); 
     466            ivState.lastUsedTransformation = currentMatrix; 
     467 
     468#ifdef DEBUG_IV_PLUGIN 
     469            if (osg::isNotifyEnabled(osg::DEBUG_INFO)) { 
     470                osg::notify(osg::DEBUG_INFO) << 
     471                          " uses local transformation:" << std::endl; 
     472                notifyAboutMatrixContent(osg::DEBUG_INFO, 
     473                          SbMatrix((SbMat&)(*osg::Matrixf(m).ptr()))); 
     474            } 
     475#endif 
     476        } 
     477    } 
     478} 
     479/////////////////////////////////////////////////////////////////// 
     480void 
     481ConvertFromInventor::ivPushState(const SoCallbackAction *action, 
     482                                 const SoNode *initiator, const int flags, 
     483                                 osg::Group *root) 
     484{ 
     485    assert(ivStateStack.size() >= 1 && "There must be at least one " 
     486           "value in the ivStateStack to use ivPushState function."); 
     487 
     488    // APPEND_AT_PUSH 
     489    if (flags & IvStateItem::APPEND_AT_PUSH) 
     490        appendNode(root, action); 
     491 
     492    // Push state 
     493    ivStateStack.push(IvStateItem(ivStateStack.top(), action, initiator, flags, root)); 
     494 
     495} 
     496/////////////////////////////////////////////////////////////////// 
     497void 
     498ConvertFromInventor::ivPopState(const SoCallbackAction *action, 
     499                                const SoNode *initiator) 
     500{ 
     501    bool multipop; 
     502    do { 
     503        assert(ivStateStack.size() >= 2 && "There must be at least two " 
     504               "values in the ivStateStack to use ivPopState function."); 
     505 
     506        // Get multipop value 
     507        IvStateItem ivState = ivStateStack.top(); 
     508        multipop = ivState.flags & IvStateItem::MULTI_POP; 
     509        assert(multipop || 
     510               ivState.pushInitiator == initiator && 
     511               "ivStateStack push was initiated by different node."); 
     512 
     513        // Get osgStateRoot (note: we HAVE TO reference it) 
     514        osg::Group *stateRoot = ivState.osgStateRoot; 
     515        osg::ref_ptr<osg::Group> r = stateRoot; 
     516/*    assert(strcmp(stateRoot->className(), "Group") == 0 && 
     517           "IvStateStack osg graph is expected to be " 
     518           "headed by osg::Group"); 
     519        if (stateRoot->getNumChildren() == 1) { 
     520            r = stateRoot->getChild(0)->asGroup(); 
     521            osg::notify(osg::FATAL) << stateRoot->className() << std::endl; 
     522            osg::notify(osg::FATAL) << stateRoot->getChild(0)->className() << std::endl; 
     523            exit(0); 
     524            assert(r != NULL && "Node must be group."); 
     525        }*/ 
     526 
     527        // Pop state 
     528        ivStateStack.pop(); 
     529 
     530        // Update state from already popped values 
     531        if ((ivState.flags & (IvStateItem::UPDATE_STATE | 
     532            IvStateItem::UPDATE_STATE_EXCEPT_TRANSFORM)) != 0) { 
     533            IvStateItem &newTop = ivStateStack.top(); 
     534            newTop.currentTexture = ivState.currentTexture; 
     535            newTop.currentLights = ivState.currentLights; 
     536            newTop.currentGLProgram = ivState.currentGLProgram; 
     537        } 
     538 
     539        // APPEND_AT_PUSH 
     540        if (!(ivState.flags & IvStateItem::APPEND_AT_PUSH)) 
     541            appendNode(r, action); 
     542 
     543    } while (multipop); 
     544 
     545} 
     546/////////////////////////////////////////////////////////////////// 
     547SoCallbackAction::Response 
     548ConvertFromInventor::preNode(void* data, SoCallbackAction* action, 
     549                             const SoNode* node) 
     550{ 
     551#ifdef DEBUG_IV_PLUGIN 
     552    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preNode()    " 
     553              << node->getTypeId().getName().getString() << std::endl; 
     554#endif 
     555 
     556    if (nodePreservesState(node)) { 
     557 
     558        // push state 
     559        ConvertFromInventor *thisPtr = (ConvertFromInventor *) data; 
     560        thisPtr->ivPushState(action, node); 
     561#ifdef DEBUG_IV_PLUGIN 
     562        if (osg::isNotifyEnabled(osg::DEBUG_INFO)) { 
     563            osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "push state, saved values: " << std::endl; 
     564            notifyAboutMatrixContent(osg::DEBUG_INFO, action->getModelMatrix()); 
     565        } 
     566#endif 
     567    } 
     568 
     569    return SoCallbackAction::CONTINUE; 
     570} 
     571//////////////////////////////////////////////////////////////////// 
     572SoCallbackAction::Response 
     573ConvertFromInventor::postNode(void* data, SoCallbackAction* action, 
    151574                              const SoNode* node) 
    152575{ 
    153576#ifdef DEBUG_IV_PLUGIN 
    154     osg::notify(osg::INFO) << "preShape()    "  
     577    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postNode()   " 
    155578              << node->getTypeId().getName().getString() << std::endl; 
    156579#endif 
    157580 
     581    if (nodePreservesState(node)) { 
     582 
     583        // pop state 
     584        ConvertFromInventor *thisPtr = (ConvertFromInventor *) data; 
     585        assert(thisPtr->ivStateStack.size() > 0 && "ivStackState underflow"); 
     586        thisPtr->ivPopState(action, node); 
     587 
     588#ifdef DEBUG_IV_PLUGIN 
     589        if (osg::isNotifyEnabled(osg::DEBUG_INFO)) { 
     590            osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << 
     591                      "pop state, restored transformation: " << std::endl; 
     592            notifyAboutMatrixContent(osg::DEBUG_INFO, action->getModelMatrix()); 
     593        } 
     594#endif 
     595    } 
     596 
     597    return SoCallbackAction::CONTINUE; 
     598} 
     599/////////////////////////////////////////////////////////////////// 
     600SoCallbackAction::Response 
     601ConvertFromInventor::preTransformSeparator(void* data, SoCallbackAction* action, 
     602                             const SoNode* node) 
     603{ 
     604#ifdef DEBUG_IV_PLUGIN 
     605    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preTransformSeparator()    " 
     606              << node->getTypeId().getName().getString() << std::endl; 
     607#endif 
     608 
     609    // push state 
     610    ConvertFromInventor *thisPtr = (ConvertFromInventor *) data; 
     611    thisPtr->ivPushState(action, node, IvStateItem::UPDATE_STATE_EXCEPT_TRANSFORM, 
     612                         new osg::Group()); 
     613 
     614    return SoCallbackAction::CONTINUE; 
     615} 
     616//////////////////////////////////////////////////////////////////// 
     617SoCallbackAction::Response 
     618ConvertFromInventor::postTransformSeparator(void* data, SoCallbackAction* action, 
     619                              const SoNode* node) 
     620{ 
     621#ifdef DEBUG_IV_PLUGIN 
     622    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postTransformSeparator()   " 
     623              << node->getTypeId().getName().getString() << std::endl; 
     624#endif 
     625 
     626    // pop state 
     627    ConvertFromInventor *thisPtr = (ConvertFromInventor *) data; 
     628    assert(thisPtr->ivStateStack.size() > 0 && "ivStackState underflow"); 
     629    thisPtr->ivPopState(action, node); 
     630 
     631    return SoCallbackAction::CONTINUE; 
     632} 
     633/////////////////////////////////////////////////////////////////// 
     634SoCallbackAction::Response 
     635ConvertFromInventor::preLOD(void* data, SoCallbackAction* action, 
     636                            const SoNode* node) 
     637{ 
     638#ifdef DEBUG_IV_PLUGIN 
     639    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preLOD()   " 
     640              << node->getTypeId().getName().getString() << std::endl; 
     641#endif 
     642 
     643    // init values 
     644    ConvertFromInventor* thisPtr = (ConvertFromInventor*)data; 
     645 
     646    // SoLOD 
     647    // Note: It is not possible to convert SoLOD to osg:LOD 
     648    // in any non-complex algorithm, because SoLOD does not preserves 
     649    // traversal state (like SoSeparator). Thus, following example 
     650    // can not be easily converted: 
     651    // 
     652    // SoLOD { 
     653    //   range [...] 
     654    //   Complexity { value 0.1 } 
     655    //   Complexity { value 0.2 } 
     656    //   Complexity { value 0.3 } 
     657    // } 
     658    // Sphere {} 
     659    // 
     660    // It was decided that it is necessary to preprocess scene 
     661    // in a way to avoid any state to come out of SoLOD. For example: 
     662    // 
     663    // SoLOD { 
     664    //   range [...] 
     665    //   Separator { 
     666    //     Complexity { value 0.1 } 
     667    //     DEF mySphere Sphere {} 
     668    //   } 
     669    //   Separator { 
     670    //     Complexity { value 0.2 } 
     671    //     USE mySphere 
     672    //   } 
     673    //   Separator { 
     674    //     Complexity { value 0.3 } 
     675    //     USE mySphere 
     676    //   } 
     677    // } 
     678    // 
     679    // Such scene can be converted easily to OSG. 
     680    if (node->isOfType(SoLOD::getClassTypeId())) { 
     681 
     682        thisPtr->ivPushState(action, node, IvStateItem::KEEP_CHILDREN_ORDER, 
     683                             new osg::LOD); 
     684        thisPtr->ivStateStack.top().keepChildrenOrderParent = node; 
     685 
     686        return SoCallbackAction::CONTINUE; 
     687    } 
     688 
     689    return SoCallbackAction::CONTINUE; 
     690} 
     691////////////////////////////////////////////////////////////// 
     692SoCallbackAction::Response 
     693ConvertFromInventor::postLOD(void* data, SoCallbackAction* action, 
     694                             const SoNode* node) 
     695{ 
     696#ifdef DEBUG_IV_PLUGIN 
     697    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postLOD()  " 
     698              << node->getTypeId().getName().getString() << std::endl; 
     699#endif 
     700 
     701    // SoGroup -> do nothing 
     702    if (node->getTypeId() == SoGroup::getClassTypeId()) 
     703        return SoCallbackAction::CONTINUE; 
     704 
     705    // init values 
     706    ConvertFromInventor* thisPtr = (ConvertFromInventor*)data; 
     707    IvStateItem &ivState = thisPtr->ivStateStack.top(); 
     708 
     709    // SoLOD 
     710    if (node->isOfType(SoLOD::getClassTypeId())) { 
     711 
     712        osg::LOD *lod = dynamic_cast<osg::LOD*>(ivState.osgStateRoot.get()); 
     713        SoLOD *ivLOD = (SoLOD*)node; 
     714 
     715        // LOD center 
     716        SbVec3f ivCenter = ivLOD->center.getValue(); 
     717        lod->setCenter(osg::Vec3(ivCenter[0], ivCenter[1], ivCenter[2])); 
     718 
     719        // Verify the number of children and range values 
     720        int num = lod->getNumChildren(); 
     721        if (ivLOD->range.getNum()+1 != num && 
     722            !(num == 0 && ivLOD->range.getNum() == 0)) { 
     723            osg::notify(osg::WARN) << NOTIFY_HEADER << 
     724                      "Warning: SoLOD does not contain " 
     725                      "correct data in range field." << std::endl; 
     726            if (ivLOD->range.getNum()+1 < num) { 
     727                lod->removeChildren(ivLOD->range.getNum() + 1, 
     728                                    num - ivLOD->range.getNum() - 1); 
     729                num = ivLOD->range.getNum() + 1; 
     730            } 
     731        } 
     732 
     733        // Get the ranges and set it 
     734        if (num > 0) { 
     735            if (num == 1) 
     736                lod->setRange(0, 0.0, FLT_MAX); 
     737            else { 
     738                lod->setRange(0, 0.0, ivLOD->range[0]); 
     739                for (int i = 1; i < num-1; i++) 
     740                    lod->setRange(i, ivLOD->range[i-1], ivLOD->range[i]); 
     741                lod->setRange(num-1, ivLOD->range[num-2], FLT_MAX); 
     742            } 
     743        } 
     744 
     745#ifdef DEBUG_IV_PLUGIN 
     746        osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << 
     747                  "Appending osg::LOD with " << num << " children." << std::endl; 
     748#endif 
     749 
     750        assert(ivState.keepChildrenOrderParent == node && 
     751               "Current node is not the root of keepChildrenOrder graph."); 
     752        thisPtr->ivPopState(action, node); 
     753 
     754        return SoCallbackAction::CONTINUE; 
     755    } 
     756 
     757    return SoCallbackAction::CONTINUE; 
     758} 
     759/////////////////////////////////////////////////////////////////// 
     760SoCallbackAction::Response 
     761ConvertFromInventor::preShape(void* data, SoCallbackAction* action, 
     762                              const SoNode* node) 
     763{ 
     764#ifdef DEBUG_IV_PLUGIN 
     765    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preShape()   " 
     766              << node->getTypeId().getName().getString() << std::endl; 
     767#endif 
     768 
    158769    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 
    159770 
    160771    // Normal and color binding map from Inventor to OSG 
    161     static std::map<SoNormalBinding::Binding, osg::Geometry::AttributeBinding>  
     772    static std::map<SoNormalBinding::Binding, osg::Geometry::AttributeBinding> 
    162773        normBindingMap; 
    163774    static std::map<SoMaterialBinding::Binding, osg::Geometry::AttributeBinding> 
     
    166777    if (firstTime) 
    167778    { 
    168         normBindingMap[SoNormalBinding::OVERALL]   
     779        normBindingMap[SoNormalBinding::OVERALL] 
    169780                                        = osg::Geometry::BIND_OVERALL; 
    170         normBindingMap[SoNormalBinding::PER_PART]  
     781        normBindingMap[SoNormalBinding::PER_PART] 
    171782                                        = osg::Geometry::BIND_PER_PRIMITIVE; 
    172         normBindingMap[SoNormalBinding::PER_PART_INDEXED]  
     783        normBindingMap[SoNormalBinding::PER_PART_INDEXED] 
    173784                                        = osg::Geometry::BIND_PER_PRIMITIVE; 
    174         normBindingMap[SoNormalBinding::PER_FACE]  
     785        normBindingMap[SoNormalBinding::PER_FACE] 
    175786                                        = osg::Geometry::BIND_PER_PRIMITIVE; 
    176         normBindingMap[SoNormalBinding::PER_FACE_INDEXED]  
     787        normBindingMap[SoNormalBinding::PER_FACE_INDEXED] 
    177788                                        = osg::Geometry::BIND_PER_PRIMITIVE; 
    178         normBindingMap[SoNormalBinding::PER_VERTEX]  
     789        normBindingMap[SoNormalBinding::PER_VERTEX] 
    179790                                        = osg::Geometry::BIND_PER_VERTEX; 
    180         normBindingMap[SoNormalBinding::PER_VERTEX_INDEXED]  
     791        normBindingMap[SoNormalBinding::PER_VERTEX_INDEXED] 
    181792                                        = osg::Geometry::BIND_PER_VERTEX; 
    182793 
    183         colBindingMap[SoMaterialBinding::OVERALL]  
     794        colBindingMap[SoMaterialBinding::OVERALL] 
    184795                                        = osg::Geometry::BIND_OVERALL; 
    185796        colBindingMap[SoMaterialBinding::PER_PART] 
    186797                                        = osg::Geometry::BIND_PER_PRIMITIVE; 
    187         colBindingMap[SoMaterialBinding::PER_PART_INDEXED]  
     798        colBindingMap[SoMaterialBinding::PER_PART_INDEXED] 
    188799                                        = osg::Geometry::BIND_PER_PRIMITIVE; 
    189800        colBindingMap[SoMaterialBinding::PER_FACE] 
    190801                                        = osg::Geometry::BIND_PER_PRIMITIVE; 
    191         colBindingMap[SoMaterialBinding::PER_FACE_INDEXED]  
     802        colBindingMap[SoMaterialBinding::PER_FACE_INDEXED] 
    192803                                        = osg::Geometry::BIND_PER_PRIMITIVE; 
    193         colBindingMap[SoMaterialBinding::PER_VERTEX]  
     804        colBindingMap[SoMaterialBinding::PER_VERTEX] 
    194805                                        = osg::Geometry::BIND_PER_VERTEX; 
    195         colBindingMap[SoMaterialBinding::PER_VERTEX_INDEXED]  
     806        colBindingMap[SoMaterialBinding::PER_VERTEX_INDEXED] 
    196807                                        = osg::Geometry::BIND_PER_VERTEX; 
    197808 
     
    223834    thisPtr->colors.clear(); 
    224835    thisPtr->textureCoords.clear(); 
    225      
     836 
    226837    return SoCallbackAction::CONTINUE; 
    227838} 
     
    230841//for matrices                                           // 
    231842/////////////////////////////////////////////////////////// 
    232 void ConvertFromInventor::transposeMatrix(osg::Matrix& mat) 
     843void 
     844ConvertFromInventor::transposeMatrix(osg::Matrix& mat) 
    233845{ 
    234846    float tmp; 
    235     for (int j = 0; j < 4; j++)  
    236     { 
    237         for (int i = j + 1; i < 4; i++)  
     847    for (int j = 0; j < 4; j++) 
     848    { 
     849        for (int i = j + 1; i < 4; i++) 
    238850        { 
    239851            tmp = mat.operator()(j,i); 
     
    245857} 
    246858//////////////////////////////////////////////////////////////////// 
    247 SoCallbackAction::Response  
    248 ConvertFromInventor::postShape(void* data, SoCallbackAction* action,  
     859SoCallbackAction::Response 
     860ConvertFromInventor::postShape(void* data, SoCallbackAction* action, 
    249861                               const SoNode* node) 
    250862{ 
    251863#ifdef DEBUG_IV_PLUGIN 
    252     osg::notify(osg::INFO) << "postShape()   " 
     864    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postShape()  " 
    253865              << node->getTypeId().getName().getString() << std::endl; 
    254866#endif 
     
    291903        SbColor ambient, diffuse, specular, emission; 
    292904        float transparency, shininess; 
    293         action->getMaterial(ambient, diffuse, specular, emission, shininess,  
     905        action->getMaterial(ambient, diffuse, specular, emission, shininess, 
    294906                            transparency, 0); 
    295907        (*cols)[0].set(diffuse[0], diffuse[1], diffuse[2], 1.0 - transparency); 
     
    306918 
    307919    if (thisPtr->textureCoords.empty()) 
    308         osg::notify(osg::INFO)<<"tex coords not found"<<std::endl; 
     920        osg::notify(osg::DEBUG_INFO)<<"tex coords not found"<<std::endl; 
    309921    else { 
    310          
     922 
    311923        // report texture coordinate conditions 
    312924        if (action->getNumTextureCoordinates()>0) 
    313             osg::notify(osg::INFO)<<"tex coords found"<<std::endl; 
     925            osg::notify(osg::DEBUG_INFO)<<"tex coords found"<<std::endl; 
    314926        else 
    315            osg::notify(osg::INFO)<<"tex coords generated"<<std::endl; 
     927           osg::notify(osg::DEBUG_INFO)<<"tex coords generated"<<std::endl; 
    316928 
    317929        // Get the texture transformation matrix 
     
    322934        osg::Matrix identityMat; 
    323935        identityMat.makeIdentity(); 
    324         osg::ref_ptr<osg::Vec2Array> texCoords  
     936        osg::ref_ptr<osg::Vec2Array> texCoords 
    325937            = new osg::Vec2Array(thisPtr->textureCoords.size()); 
    326938        if (textureMat == identityMat) 
     
    336948            { 
    337949                osg::Vec3 transVec = textureMat.preMult( 
    338                         osg::Vec3(thisPtr->textureCoords[i][0],  
     950                        osg::Vec3(thisPtr->textureCoords[i][0], 
    339951                                  thisPtr->textureCoords[i][1], 
    340952                                  0.0)); 
     
    345957        geometry->setTexCoordArray(0, texCoords.get()); 
    346958    } 
    347      
     959 
    348960    // Set the parameters for the geometry 
    349961 
     
    353965    osg::ref_ptr<osg::StateSet> stateSet = thisPtr->getStateSet(action); 
    354966    geometry->setStateSet(stateSet.get()); 
    355      
     967 
    356968    // Add the geoset to a geode 
    357969    osg::ref_ptr<osg::Geode> geode = new osg::Geode; 
     
    363975        geode->setName(name); 
    364976    } 
    365     // Add geode to scenegraph 
    366     thisPtr->groupStack.top()->addChild(geode.get()); 
     977 
     978    // Transformation and scene graph building 
     979    thisPtr->appendNode(geode.get(), action); 
    367980 
    368981    return SoCallbackAction::CONTINUE; 
    369982} 
    370983/////////////////////////////////////////////////////////////// 
    371 SoCallbackAction::Response  
    372 ConvertFromInventor::preTexture(void* data, SoCallbackAction *, 
    373                                 const SoNode* node) 
    374 { 
    375 #ifdef DEBUG_IV_PLUGIN 
    376     osg::notify(osg::INFO) << "preTexture()  "  
    377               << node->getTypeId().getName().getString() << std::endl; 
    378 #endif 
    379      
     984SoCallbackAction::Response 
     985ConvertFromInventor::postTexture(void* data, SoCallbackAction *, 
     986                                 const SoNode* node) 
     987{ 
     988#ifdef DEBUG_IV_PLUGIN 
     989    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postTexture()  " 
     990              << node->getTypeId().getName().getString(); 
     991    if (node->isOfType(SoTexture2::getClassTypeId())) { 
     992        SoTexture2 *t = (SoTexture2*)node; 
     993        if (t->filename.getValue().getLength()) 
     994            osg::notify(osg::DEBUG_INFO) << "  "  << t->filename.getValue().getString(); 
     995    } 
     996    osg::notify(osg::DEBUG_INFO) << std::endl; 
     997#endif 
     998 
    380999    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 
    381      
    382     if (thisPtr->soTexStack.size()) 
    383         thisPtr->soTexStack.pop(); 
    384     thisPtr->soTexStack.push(node); 
    385          
     1000    bool texturingEnabled = false; 
     1001 
     1002    // Texture2 
     1003    if (node->isOfType(SoTexture2::getClassTypeId())) { 
     1004 
     1005        // Check whether texturing was enabled by the texture node 
     1006        SoTexture2 *t = (SoTexture2*)node; 
     1007        SbVec2s size; 
     1008        int nc; 
     1009        const unsigned char *data = t->image.getValue(size, nc); 
     1010        texturingEnabled = t->filename.getValue().getLength() || 
     1011                           (data && size != SbVec2s(0,0)); 
     1012    } 
     1013 
     1014#ifdef __COIN__ 
     1015 
     1016    // SoVRMLImageTexture 
     1017    if (node->isOfType(SoVRMLImageTexture::getClassTypeId())) { 
     1018 
     1019        // Check whether texturing was enabled by the texture node 
     1020        SoVRMLImageTexture *t = (SoVRMLImageTexture*)node; 
     1021        texturingEnabled = t->url.getNum() > 1 || (t->url.getNum() == 1 && t->url[0].getLength() > 0); 
     1022    } 
     1023 
     1024    // SoVRMLAppearance 
     1025    if (node->isOfType(SoVRMLAppearance::getClassTypeId())) { 
     1026 
     1027        // If SoVRMLAppearance is present and there is no texture 
     1028        // inside, disable texturing 
     1029        // FIXME: should SoVRMLAppearance really disable texturing 
     1030        // when not containing SoVRMLImageTexture? Coin is not doing that, 
     1031        // but it can be Coin bug. 
     1032        SoVRMLAppearance *a = (SoVRMLAppearance*)node; 
     1033        if (a->texture.getValue() == NULL) 
     1034            thisPtr->ivStateStack.top().currentTexture = NULL; 
     1035 
     1036        // Do not try to "optimize" this code by removing the return 
     1037    // and use the one at the end of the function. 
     1038    // It would break the case when there is texture inside 
     1039    // the appearance node. 
     1040        return SoCallbackAction::CONTINUE; 
     1041    } 
     1042 
     1043#endif /* __COIN__ */ 
     1044 
     1045    // Set current texture 
     1046    if (texturingEnabled) 
     1047        thisPtr->ivStateStack.top().currentTexture = node; 
     1048    else 
     1049        thisPtr->ivStateStack.top().currentTexture = NULL; 
     1050 
    3861051    return SoCallbackAction::CONTINUE; 
    3871052} 
    388 ////////////////////////////////////////////////////////////////////////////////// 
    389 SoCallbackAction::Response  
    390 ConvertFromInventor::preVRMLAppearance(void* data, SoCallbackAction* action, 
    391                                          const SoNode* node) 
    392 { 
    393 #ifdef DEBUG_IV_PLUGIN 
    394     osg::notify(osg::INFO) << "preVRMLAppearance()  "  
    395               << node->getTypeId().getName().getString() << std::endl; 
    396 #endif 
    397  
    398 #ifdef __COIN__ 
    399     ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 
    400  
    401     // If there is a VRML appearance node without a texture node, then 
    402     // we push a NULL texture onto the stack 
    403     bool foundTex = false; 
    404     SoChildList *kids = node->getChildren(); 
    405     for (int i=0; i<kids->getLength(); i++) { 
    406         SoNode* kid = (SoNode*)kids->get(i); 
    407         if (kid->isOfType(SoVRMLMaterial::getClassTypeId())) { 
    408             thisPtr->appearanceName = kid->getName(); 
    409         } 
    410         if (kid->isOfType(SoVRMLTexture::getClassTypeId())) { 
    411             foundTex = true; 
    412         } 
    413     } 
    414     if (!foundTex) { 
    415         thisPtr->soTexStack.push(NULL); 
    416         thisPtr->inAppearanceWithNoTexture = true; 
    417     } 
    418 #endif 
    419     return SoCallbackAction::CONTINUE; 
    420 } 
    421  
    422 ////////////////////////////////////////////////////////////////////////////////// 
    423 SoCallbackAction::Response  
    424 ConvertFromInventor::preVRMLImageTexture(void* data, SoCallbackAction* action, 
    425                                          const SoNode* node) 
    426 { 
    427 #ifdef DEBUG_IV_PLUGIN 
    428     osg::notify(osg::INFO) << "preVRMLImageTexture()  "  
    429               << node->getTypeId().getName().getString() << std::endl; 
    430 #endif 
    431  
    432     ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 
    433  
    434     if (thisPtr->soTexStack.size()) 
    435         thisPtr->soTexStack.pop(); 
    436     thisPtr->soTexStack.push(node); 
    437  
    438     return SoCallbackAction::CONTINUE; 
    439 } 
    4401053////////////////////////////////////////////////////////////////// 
    441 void ConvertFromInventor::transformLight(SoCallbackAction* action,  
    442                                          const SbVec3f& vec,  
     1054void ConvertFromInventor::transformLight(SoCallbackAction* action, 
     1055                                         const SbVec3f& vec, 
    4431056                                         osg::Vec3& transVec) 
    4441057{ 
     
    4501063} 
    4511064/////////////////////////////////////////////////////////////////// 
    452 SoCallbackAction::Response  
    453 ConvertFromInventor::preLight(void* data, SoCallbackAction* action,  
     1065SoCallbackAction::Response 
     1066ConvertFromInventor::preLight(void* data, SoCallbackAction* action, 
    4541067                              const SoNode* node) 
    4551068{ 
    4561069#ifdef DEBUG_IV_PLUGIN 
    457     osg::notify(osg::INFO) << "preLight()  "  
     1070    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preLight()   " 
    4581071              << node->getTypeId().getName().getString() << std::endl; 
    4591072#endif 
    4601073 
    4611074    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 
    462     static int lightNum = 1; 
    463      
     1075 
    4641076    // Return if the light is not on 
    4651077    const SoLight* ivLight = (const SoLight*) node; 
     
    4671079        return SoCallbackAction::CONTINUE; 
    4681080 
     1081    // Create new OSG light 
     1082    IvStateItem &ivState = thisPtr->ivStateStack.top(); 
    4691083    osg::ref_ptr<osg::Light> osgLight = new osg::Light; 
    470     osgLight->setLightNum(lightNum++); 
    471  
     1084 
     1085    // Light name 
    4721086    const char* name = ivLight->getName().getString(); 
    4731087    osgLight->setName(name); 
    474      
     1088 
    4751089    // Get color and intensity 
    4761090    SbVec3f lightColor = ivLight->color.getValue(); 
     
    4781092 
    4791093    // Set color and intensity 
     1094    osgLight->setAmbient(osg::Vec4(0.f, 0.f, 0.f, 1.f)); 
    4801095    osgLight->setDiffuse(osg::Vec4(lightColor[0] * intensity, 
    4811096                                   lightColor[1] * intensity, 
    4821097                                   lightColor[2] * intensity, 1)); 
    483  
     1098    osgLight->setSpecular(osg::Vec4(lightColor[0] * intensity, 
     1099                                    lightColor[1] * intensity, 
     1100                                    lightColor[2] * intensity, 1)); 
     1101 
     1102    // Light type 
    4841103    if (node->isOfType(SoDirectionalLight::getClassTypeId())) 
    4851104    { 
    4861105        SoDirectionalLight *dirLight = (SoDirectionalLight *) node; 
    487          
     1106 
     1107#if 1 // Let's place the light to its place in scene graph instead of 
     1108      // old approach of global light group. 
     1109        SbVec3f l(dirLight->direction.getValue()); 
     1110        osgLight->setPosition(osg::Vec4(l[0], l[1], l[2] , 0.)); 
     1111#else 
    4881112        osg::Vec3 transVec; 
    4891113        thisPtr->transformLight(action, dirLight->direction.getValue(), transVec); 
    490         osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(),  
    491                                         transVec.z(), 0)); 
     1114        osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(), 
     1115                                        transVec.z(), 0.)); 
     1116#endif 
    4921117    } 
    4931118    else if (node->isOfType(SoPointLight::getClassTypeId())) 
     
    4951120        SoPointLight* ptLight = (SoPointLight *) node; 
    4961121 
     1122#if 1 // Let's place the light to its place in scene graph instead of 
     1123      // old approach of global light group. 
     1124        SbVec3f l(ptLight->location.getValue()); 
     1125        osgLight->setPosition(osg::Vec4(l[0], l[1], l[2] , 1.)); 
     1126#else 
    4971127        osg::Vec3 transVec; 
    4981128        thisPtr->transformLight(action, ptLight->location.getValue(), transVec); 
    499         osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(),  
    500                                         transVec.z(), 0)); 
     1129        osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(), 
     1130                                        transVec.z(), 1.)); 
     1131#endif 
    5011132    } 
    5021133    else if (node->isOfType(SoSpotLight::getClassTypeId())) 
     
    5071138        osgLight->setSpotCutoff(spotLight->cutOffAngle.getValue()*180.0/osg::PI); 
    5081139 
     1140#if 1 // Let's place the light to its place in scene graph instead of 
     1141      // old approach of global light group. 
     1142        SbVec3f l(spotLight->location.getValue()); 
     1143        osgLight->setPosition(osg::Vec4(l[0], l[1], l[2] , 1.)); 
     1144        l = spotLight->direction.getValue(); 
     1145        osgLight->setDirection(osg::Vec3(l[0], l[1], l[2])); 
     1146#else 
    5091147        osg::Vec3 transVec; 
    5101148        thisPtr->transformLight(action, spotLight->location.getValue(), transVec); 
    511         osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(),  
    512                                         transVec.z(), 0)); 
     1149        osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(), 
     1150                                        transVec.z(), 1.)); 
    5131151 
    5141152        thisPtr->transformLight(action, spotLight->direction.getValue(),transVec); 
    515         osgLight->setDirection(osg::Vec3(transVec.x(), transVec.y(),  
     1153        osgLight->setDirection(osg::Vec3(transVec.x(), transVec.y(), 
    5161154                                         transVec.z())); 
    517     } 
    518   
    519     // Add light to list in the current level 
    520     if (thisPtr->lightStack.size()) 
    521     { 
    522         LightList lightList; 
    523         lightList = thisPtr->lightStack.top(); 
    524         lightList.push_back(osgLight.get()); 
    525         thisPtr->lightStack.pop(); 
    526         thisPtr->lightStack.push(lightList); 
    527     } 
    528  
    529     // add a light source node to the scene graph 
     1155#endif 
     1156    } 
     1157 
     1158    // Attenuation 
     1159    if (!node->isOfType(SoDirectionalLight::getClassTypeId())) { 
     1160        SbVec3f att = action->getLightAttenuation(); 
     1161        osgLight->setConstantAttenuation(att[2]); 
     1162        osgLight->setLinearAttenuation(att[1]); 
     1163        osgLight->setQuadraticAttenuation(att[0]); 
     1164    } else { 
     1165        // keep default light settings for directional light, e.g. 
     1166        // no attenuation 
     1167    } 
     1168 
     1169    // Append the light into the scene and onto the state stack 
     1170    osgLight->setLightNum(ivState.currentLights.size()); 
     1171    ivState.currentLights.push_back(osgLight); 
     1172 
    5301173    osg::ref_ptr<osg::LightSource> ls = new osg::LightSource(); 
    5311174    ls->setLight(osgLight.get()); 
    5321175    ls->setName(ivLight->getName().getString()); 
    533     if (thisPtr->lightGroup == NULL) { 
    534         thisPtr->lightGroup = new osg::Group; 
    535         thisPtr->lightGroup->setName("IvLightGroup"); 
    536         thisPtr->_root->addChild(thisPtr->lightGroup.get()); 
    537     } 
    538     thisPtr->lightGroup->addChild(ls.get()); 
     1176#if 1 // Let's place the light to its place in scene graph instead of 
     1177      // old approach of global light group. 
     1178    thisPtr->ivPushState(action, node, 
     1179              IvStateItem::MULTI_POP | IvStateItem::UPDATE_STATE | 
     1180              IvStateItem::APPEND_AT_PUSH, ls.get()); 
     1181#else 
     1182    if (!(thisPtr->lightGroup.get())) 
     1183        thisPtr->lightGroup = new osg::Group(); 
     1184    thisPtr->lightGroup->addChild(ls); 
     1185#endif 
     1186 
     1187    return SoCallbackAction::CONTINUE; 
     1188} 
     1189/////////////////////////////////////////////////////////////////// 
     1190SoCallbackAction::Response 
     1191ConvertFromInventor::preEnvironment(void* data, SoCallbackAction* action, 
     1192                                    const SoNode* node) 
     1193{ 
     1194#ifdef DEBUG_IV_PLUGIN 
     1195    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preLight()   " 
     1196              << node->getTypeId().getName().getString() << std::endl; 
     1197#endif 
     1198 
     1199    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 
     1200    IvStateItem &ivState = thisPtr->ivStateStack.top(); 
     1201 
     1202    ivState.currentAmbientLight = ((SoEnvironment*)node)->ambientColor.getValue() * 
     1203                                  ((SoEnvironment*)node)->ambientIntensity.getValue(); 
     1204 
     1205    return SoCallbackAction::CONTINUE; 
     1206} 
     1207/////////////////////////////////////////////////////////////////// 
     1208#ifdef INVENTOR_SHADERS_AVAILABLE 
     1209static bool 
     1210convertShader(osg::Shader::Type osgShaderType, 
     1211              const SoShaderObject *ivShader, 
     1212              osg::Program *osgProgram) 
     1213{ 
     1214    // NULL shader is not converted while returning success 
     1215    if (ivShader == NULL) 
     1216        return true; 
     1217 
     1218    // Create shader 
     1219    osg::ref_ptr<osg::Shader> osgShader = new osg::Shader(osgShaderType); 
     1220    if (ivShader->sourceType.getValue() == SoShaderObject::FILENAME) 
     1221        osgShader->loadShaderSourceFromFile(ivShader->sourceProgram.getValue().getString()); 
     1222    else 
     1223    if (ivShader->sourceType.getValue() == SoShaderObject::GLSL_PROGRAM) 
     1224        osgShader->setShaderSource(ivShader->sourceProgram.getValue().getString()); 
     1225    else { 
     1226        osg::notify(osg::WARN) << NOTIFY_HEADER << "Can not convert " 
     1227                  << "shader. Unsupported shader language." << std::endl; 
     1228        return false; 
     1229    } 
     1230 
     1231    return osgProgram->addShader(osgShader); 
     1232} 
     1233#endif // INVENTOR_SHADERS_AVAILABLE 
     1234/////////////////////////////////////////////////////////////////// 
     1235SoCallbackAction::Response 
     1236ConvertFromInventor::preShaderProgram(void* data, SoCallbackAction* action, 
     1237                              const SoNode* node) 
     1238{ 
     1239#ifdef DEBUG_IV_PLUGIN 
     1240    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preShaderProgram()  " 
     1241              << node->getTypeId().getName().getString() << std::endl; 
     1242#endif 
     1243 
     1244#ifdef INVENTOR_SHADERS_AVAILABLE 
     1245 
     1246    ConvertFromInventor *thisPtr = (ConvertFromInventor*)data; 
     1247    IvStateItem &ivState = thisPtr->ivStateStack.top(); 
     1248 
     1249    // Get Inventor nodes 
     1250    // Note: Shaders are available since Coin 2.5 (including 
     1251    // geometry shader) 
     1252    const SoShaderProgram *ivProgram = (const SoShaderProgram*)node; 
     1253    const SoVertexShader *ivVertexShader = NULL; 
     1254    const SoGeometryShader *ivGeometryShader = NULL; 
     1255    const SoFragmentShader *ivFragmentShader = NULL; 
     1256 
     1257    for (int i=0, c=ivProgram->shaderObject.getNum(); i<c; i++) { 
     1258 
     1259        const SoShaderObject *shader = (const SoShaderObject*)ivProgram->shaderObject[i]; 
     1260        if (!shader->isOfType(SoShaderObject::getClassTypeId())) 
     1261            continue; 
     1262        if (shader->isActive.getValue() == FALSE) 
     1263            continue; 
     1264 
     1265        if (shader->isOfType(SoVertexShader::getClassTypeId())) 
     1266            ivVertexShader = (const SoVertexShader*)shader; 
     1267        if (shader->isOfType(SoGeometryShader::getClassTypeId())) 
     1268            ivGeometryShader = (const SoGeometryShader*)shader; 
     1269        if (shader->isOfType(SoFragmentShader::getClassTypeId())) 
     1270            ivFragmentShader = (const SoFragmentShader*)shader; 
     1271    } 
     1272 
     1273    // Create OSG shader 
     1274    osg::Program *osgProgram = new osg::Program(); 
     1275    if (!convertShader(osg::Shader::VERTEX, ivVertexShader, osgProgram)) 
     1276        osg::notify(osg::WARN) << NOTIFY_HEADER 
     1277                  << "Failed to add vertex shader." << std::endl; 
     1278    if (!convertShader(osg::Shader::GEOMETRY, ivGeometryShader, osgProgram)) 
     1279        osg::notify(osg::WARN) << NOTIFY_HEADER 
     1280                  << "Failed to add geometry shader." << std::endl; 
     1281    if (!convertShader(osg::Shader::FRAGMENT, ivFragmentShader, osgProgram)) 
     1282        osg::notify(osg::WARN) << NOTIFY_HEADER 
     1283                  << "Failed to add fragment shader." << std::endl; 
     1284 
     1285    // Put shader to the state stack 
     1286    ivState.currentGLProgram = osgProgram; 
     1287 
     1288#else 
     1289 
     1290    osg::notify(osg::WARN) << NOTIFY_HEADER << "Warning: The model " 
     1291              "contains shaders while your Inventor does not support " 
     1292              "them." << std::endl; 
     1293#endif 
    5391294 
    5401295    return SoCallbackAction::CONTINUE; 
     
    5451300{ 
    5461301    osg::ref_ptr<osg::StateSet> stateSet = new osg::StateSet; 
    547      
     1302 
    5481303    // Inherit modes from the global state 
    5491304    stateSet->clear(); 
    5501305 
     1306    // Inventor State Stack 
     1307    IvStateItem &ivState = ivStateStack.top(); 
     1308 
    5511309    // Convert the IV texture to OSG texture if any 
    5521310    osg::ref_ptr<osg::Texture2D> texture; 
    553     const SoNode *ivTexture = soTexStack.top(); 
     1311    const SoNode *ivTexture = ivState.currentTexture; 
    5541312    if (ivTexture) 
    5551313    { 
    556         osg::notify(osg::INFO)<<"Have texture"<<std::endl; 
    557  
    5581314        // Found a corresponding OSG texture object 
    5591315        if (ivToOsgTexMap[ivTexture]) 
     
    5671323            ivToOsgTexMap[ivTexture] = texture.get(); 
    5681324        } 
    569          
     1325 
    5701326        stateSet->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::ON); 
    571          
     1327 
    5721328        // propogate name 
    5731329        if(texture.valid()) 
     
    5871343                texEnv->setMode(osg::TexEnv::DECAL); 
    5881344                break; 
    589             case SoTexture2::BLEND: 
     1345            case SoTexture2::BLEND: { 
    5901346                texEnv->setMode(osg::TexEnv::BLEND); 
     1347                SbColor c(action->getTextureBlendColor()); 
     1348                texEnv->setColor(osg::Vec4(c[0], c[1], c[2], 1.f)); 
    5911349                break; 
    592 #if defined(__COIN__) && ((COIN_MAJOR_VERSION==2 && COIN_MINOR_VERSION>=2) || (COIN_MAJOR_VERSION>2)) 
     1350            } 
    5931351            // SGI's Inventor does not have REPLACE mode, but the Coin 3D library does. 
    5941352            // Coin supports REPLACE since 2.2 release, TGS Inventor from 4.0. 
    5951353            // Let's convert to the TexEnv anyway. 
    596             case SoTexture2::REPLACE: 
     1354            case 0x1E01: //SoTexture2::REPLACE: 
    5971355                texEnv->setMode(osg::TexEnv::REPLACE); 
    5981356                break; 
    599 #endif 
    6001357            default: 
     1358                osg::notify(osg::WARN) << "Unsupported TexEnv mode." << std::endl; 
    6011359                break; 
    6021360 
     
    6111369    action->getMaterial(ambient, diffuse, specular, emission, 
    6121370                shininess, transparency, 0); 
    613      
     1371 
    6141372    // Set transparency 
    6151373    SbBool hasTextureTransparency = FALSE; 
    6161374    if (ivTexture) { 
    6171375      SbVec2s tmp; 
    618       int bpp; 
     1376      int bpp = 0; 
    6191377      if (ivTexture->isOfType(SoTexture2::getClassTypeId())) 
    6201378        ((SoTexture2*)ivTexture)->image.getValue(tmp, bpp); 
     
    6241382        const SbImage *img = ((SoVRMLImageTexture*)ivTexture)->getImage(); 
    6251383        if (img) img->getValue(tmp, bpp); 
    626         else bpp = 0; 
    6271384      } 
    6281385#endif 
     
    6331390    { 
    6341391        osg::ref_ptr<osg::BlendFunc> transparency = new osg::BlendFunc; 
    635         stateSet->setAttributeAndModes(transparency.get(),  
     1392        stateSet->setAttributeAndModes(transparency.get(), 
    6361393                                       osg::StateAttribute::ON); 
    637      
     1394 
    6381395        // Enable depth sorting for transparent objects 
    6391396        stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); 
    6401397    } 
    641      
     1398 
    6421399    // Set linewidth 
    6431400    if (action->getLineWidth()) 
     
    6551412        stateSet->setAttributeAndModes(point.get(), osg::StateAttribute::ON); 
    6561413    } 
    657      
    658     // Set draw mode  
     1414 
     1415    // Set draw mode 
    6591416    switch (action->getDrawStyle()) 
    6601417    { 
     
    6641421// OSG defaults to filled draw style, so no need to set redundent state. 
    6651422            osg::PolygonMode *polygonMode = new osg::PolygonMode; 
    666             polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK,  
     1423            polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK, 
    6671424                                 osg::PolygonMode::FILL); 
    6681425            stateSet->setAttributeAndModes(polygonMode, osg::StateAttribute::ON); 
     
    6731430        { 
    6741431            osg::ref_ptr<osg::PolygonMode> polygonMode = new osg::PolygonMode; 
    675             polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK,  
     1432            polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK, 
    6761433                                 osg::PolygonMode::LINE); 
    6771434            stateSet->setAttributeAndModes(polygonMode.get(), osg::StateAttribute::ON); 
     
    6811438        { 
    6821439            osg::ref_ptr<osg::PolygonMode> polygonMode = new osg::PolygonMode; 
    683             polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK,  
     1440            polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK, 
    6841441                                 osg::PolygonMode::POINT); 
    6851442            stateSet->setAttributeAndModes(polygonMode.get(), osg::StateAttribute::ON); 
     
    6971454        cullFace->setMode(osg::CullFace::BACK); 
    6981455        stateSet->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON); 
    699     }  
     1456    } 
    7001457 
    7011458    // Set lighting 
     
    7071464        osg::ref_ptr<osg::Material> material = new osg::Material; 
    7081465 
    709         material->setAmbient(osg::Material::FRONT_AND_BACK,  
    710                              osg::Vec4(ambient[0], ambient[1], ambient[2],  
     1466        material->setAmbient(osg::Material::FRONT_AND_BACK, 
     1467                             osg::Vec4(ambient[0], ambient[1], ambient[2], 
    7111468                                       1.0 - transparency)); 
    712         material->setDiffuse(osg::Material::FRONT_AND_BACK,  
    713                              osg::Vec4(diffuse[0], diffuse[1], diffuse[2],  
     1469        material->setDiffuse(osg::Material::FRONT_AND_BACK, 
     1470                             osg::Vec4(diffuse[0], diffuse[1], diffuse[2], 
    7141471                                       1.0 - transparency)); 
    715         material->setSpecular(osg::Material::FRONT_AND_BACK,  
    716                               osg::Vec4(specular[0], specular[1], specular[2],  
     1472        material->setSpecular(osg::Material::FRONT_AND_BACK, 
     1473                              osg::Vec4(specular[0], specular[1], specular[2], 
    7171474                                        1.0 - transparency)); 
    718         material->setEmission(osg::Material::FRONT_AND_BACK,  
    719                               osg::Vec4(emission[0], emission[1], emission[2],  
     1475        material->setEmission(osg::Material::FRONT_AND_BACK, 
     1476                              osg::Vec4(emission[0], emission[1], emission[2], 
    7201477                                        1.0 - transparency)); 
    7211478        material->setTransparency(osg::Material::FRONT_AND_BACK, transparency); 
    7221479        if (specular[0] || specular[1] || specular[2]) 
    723             material->setShininess(osg::Material::FRONT_AND_BACK,  
     1480            material->setShininess(osg::Material::FRONT_AND_BACK, 
    7241481                                   shininess*128.0); 
    7251482        else 
     
    7321489        stateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON); 
    7331490 
     1491        // Set global ambient light 
     1492        // note on osg::LightModel default values: 
     1493        //   colorControl: SINGLE_COLOR, localViewer: false, twoSided: false 
     1494        osg::LightModel *lightModel = new osg::LightModel(); 
     1495        const SbColor &c = ivState.currentAmbientLight; 
     1496        lightModel->setAmbientIntensity(osg::Vec4(c[0], c[1], c[2], 1.0)); 
    7341497#if 0 
    7351498// disable as two sided lighting causes problem under NVidia, and the above osg::Material settings are single sided anway.. 
     1499update: The mentioned bug is probably just for very old NVidia drivers (commit time of the comment is 2005-03-18). 
     1500        The proper solution should be to set two sided lighting based on SoShapeHints node. Need to be developed. PCJohn-2010-01-20 
    7361501        // Set two sided lighting 
    737         osg::LightModel* lightModel = new osg::LightModel; 
    7381502        lightModel->setTwoSided(true); 
     1503#endif 
    7391504        stateSet->setAttributeAndModes(lightModel, osg::StateAttribute::ON); 
    740 #endif 
     1505 
    7411506        // Set lights 
    742         LightList lightList = lightStack.top(); 
    743         for (unsigned int i = 0; i < lightList.size(); i++) 
    744             stateSet->setAttributeAndModes(lightList[i],  
     1507        for (unsigned int i = 0; i < ivState.currentLights.size(); i++) 
     1508            stateSet->setAttributeAndModes(ivState.currentLights[i].get(), 
    7451509                                           osg::StateAttribute::ON); 
    746     } 
    747      
     1510 
     1511    } 
     1512 
     1513    // Shader program setup 
     1514    if (ivState.currentGLProgram.get() != NULL) { 
     1515        stateSet->setAttributeAndModes(ivState.currentGLProgram.get(), 
     1516                                       osg::StateAttribute::ON); 
     1517    } 
     1518 
     1519    // Shader program uniforms 
     1520    if (ivState.currentGLProgram.get() != NULL) { 
     1521        for (int i=0, c=ivState.currentGLProgram->getNumShaders(); i<c; i++) { 
     1522             const std::string &shaderCode = ivState.currentGLProgram->getShader(i)->getShaderSource(); 
     1523             if (shaderCode.find("coin_texunit0_model") != std::string::npos) { 
     1524                 int mode = (ivTexture!=NULL) ? action->getTextureModel() : 0; 
     1525                 stateSet->addUniform(new osg::Uniform("coin_texunit0_model", mode)); 
     1526                 break; 
     1527             } 
     1528        } 
     1529    } 
     1530 
    7481531    return stateSet; 
    7491532} 
     
    7531536                                          SoCallbackAction* action) 
    7541537{ 
    755     osg::notify(osg::INFO)<<"convertIVTexToOSGTex of type "<< 
    756         soNode->getTypeId().getName().getString()<<std::endl; 
     1538#ifdef DEBUG_IV_PLUGIN 
     1539    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER 
     1540              << "convertIVTexToOSGTex (" 
     1541              << soNode->getTypeId().getName().getString() 
     1542              << ")" << std::endl; 
     1543#endif 
    7571544 
    7581545    SbVec2s soSize; 
     
    7621549    const unsigned char* soImageData = action->getTextureImage(soSize, soNC); 
    7631550    if (!soImageData) { 
    764         osg::notify(osg::WARN) << "IV import warning: Error while loading texture data." << std::endl; 
     1551        osg::notify(osg::WARN) << NOTIFY_HEADER 
     1552                  << "Warning: Error while loading texture data." << std::endl; 
    7651553        return NULL; 
    7661554    } 
     
    7821570    else 
    7831571    if (soNode->isOfType(SoVRMLImageTexture::getClassTypeId())) 
    784         fileName = ((SoVRMLImageTexture*)soNode)->url.getNum() >= 1 ?  
     1572        fileName = ((SoVRMLImageTexture*)soNode)->url.getNum() >= 1 ? 
    7851573                   ((SoVRMLImageTexture*)soNode)->url.getValues(0)[0].getString() : ""; 
    7861574#endif 
    7871575    else 
    788       osg::notify(osg::WARN) << "IV import warning: Unsupported texture type: " 
    789             << soNode->getTypeId().getName().getString() << std::endl; 
    790  
    791     osg::notify(osg::INFO) << fileName << " -> "; 
     1576      osg::notify(osg::WARN) << NOTIFY_HEADER 
     1577                << " Warning: Unsupported texture type: " 
     1578                << soNode->getTypeId().getName().getString() << std::endl; 
     1579 
     1580#ifdef DEBUG_IV_PLUGIN 
     1581    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER 
     1582              << "  Converting file name: " << fileName << " -> "; 
     1583#endif 
    7921584    if (fileName[0]=='\"') fileName.erase(fileName.begin()); 
    793     if (fileName.size() > 0 && fileName[fileName.size()-1]=='\"')  
     1585    if (fileName.size() > 0 && fileName[fileName.size()-1]=='\"') 
    7941586        fileName.erase(fileName.begin()+fileName.size()-1); 
    795     osg::notify(osg::INFO) << fileName << std::endl; 
    796  
    797     // Create the osg::Image  
     1587#ifdef DEBUG_IV_PLUGIN 
     1588    osg::notify(osg::DEBUG_INFO) << fileName << std::endl; 
     1589#endif 
     1590 
     1591    // Create the osg::Image 
    7981592    osg::ref_ptr<osg::Image> osgImage = new osg::Image; 
    7991593    osgImage->setFileName(fileName); 
     
    8171611        firstTime = false; 
    8181612    } 
    819           
     1613 
    8201614    // Set texture wrap mode 
    8211615#ifdef __COIN__ 
     
    8401634    } 
    8411635 
    842     return osgTex;  
     1636    return osgTex; 
    8431637} 
    8441638/////////////////////////////////////////////////////////////////// 
    845 SoCallbackAction::Response  
    846 ConvertFromInventor::preInfo(void* data, SoCallbackAction* action,  
    847                               const SoNode* node) 
    848 { 
    849 #ifdef DEBUG_IV_PLUGIN 
    850     osg::notify(osg::INFO) << "preInfo()    "  
     1639SoCallbackAction::Response 
     1640ConvertFromInventor::preInfo(void* data, SoCallbackAction* action, 
     1641                             const SoNode* node) 
     1642{ 
     1643#ifdef DEBUG_IV_PLUGIN 
     1644    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preInfo()    " 
    8511645              << node->getTypeId().getName().getString() << std::endl; 
    8521646#endif 
     
    8571651    return SoCallbackAction::CONTINUE; 
    8581652} 
    859      
    860 /////////////////////////////////////////////////////////////////// 
    861 SoCallbackAction::Response  
    862 ConvertFromInventor::preGroup(void* data, SoCallbackAction* action,  
    863                               const SoNode* node) 
    864 { 
    865 #ifdef DEBUG_IV_PLUGIN 
    866     osg::notify(osg::INFO) << "preGroup()    "  
    867               << node->getTypeId().getName().getString() << std::endl; 
    868 #endif 
    869  
    870     ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 
    871  
    872     // Create a new Group or LOD and add it to the stack 
    873     osg::ref_ptr<osg::Group> group; 
    874     if (node->isOfType(SoLOD::getClassTypeId())) { 
    875         group = new osg::LOD; 
    876     } 
    877     else { 
    878         group = new osg::Group; 
    879     } 
    880  
    881  
    882     thisPtr->groupStack.top()->addChild(group.get()); 
    883     thisPtr->groupStack.push(group.get()); 
    884      
    885     // SoTransform nodes are not the parent of the nodes they apply to 
    886     // But are in the same separator as them  
    887     SoChildList *kids = node->getChildren(); 
    888     for (int i=0; i<kids->getLength(); i++) { 
    889         SoNode* kid = (SoNode*)kids->get(i); 
    890         if (kid->isOfType(SoTransform::getClassTypeId())) { 
    891             SoTransform* t = (SoTransform*)kid; 
    892             SbVec3f axis, center, trans, scale; 
    893             float angle; 
    894  
    895             center = t->center.getValue(); 
    896             t->rotation.getValue(axis, angle); 
    897             trans = t->translation.getValue(); 
    898             scale = t->scaleFactor.getValue(); 
    899             std::string name = t->getName().getString(); 
    900  
    901             thisPtr->addMatrixTransform(name, axis, angle, center, trans, scale); 
    902         } 
    903     } 
    904 #ifdef __COIN__ 
    905     if (node->isOfType(SoVRMLTransform::getClassTypeId())) { 
    906         std::string name; 
    907         if (thisPtr->transformInfoName != "") { 
    908             name = std::string("INFO_"); 
    909             name += thisPtr->transformInfoName.getString(); 
    910             name += "_trans"; 
    911         } 
    912         else { 
    913             name = node->getName(); 
    914         } 
    915          
    916         SoVRMLTransform* vt = (SoVRMLTransform*)node; 
    917         SbVec3f axis, center, trans, scale; 
    918         float angle; 
    919  
    920         center = vt->center.getValue(); 
    921         vt->rotation.getValue(axis, angle); 
    922         trans = vt->translation.getValue(); 
    923         scale = vt->scale.getValue(); 
    924  
    925         thisPtr->addMatrixTransform(name, axis, angle, center, trans, scale); 
    926     } 
    927 #endif 
    928     if (node->isOfType(SoSeparator::getClassTypeId())) 
    929     { 
    930         if (thisPtr->soTexStack.size()) 
    931             thisPtr->soTexStack.push(thisPtr->soTexStack.top()); 
    932         else 
    933             thisPtr->soTexStack.push(NULL); 
    934         if (thisPtr->lightStack.size()) 
    935         { 
    936             LightList lightList = thisPtr->lightStack.top(); 
    937             thisPtr->lightStack.push(lightList); 
    938         } 
    939     } 
    940  
    941     return SoCallbackAction::CONTINUE; 
    942 } 
    943 ////////////////////////////////////////////////////////////// 
    944 SoCallbackAction::Response  
    945 ConvertFromInventor::postGroup(void* data, SoCallbackAction* action,  
    946                                const SoNode* node) 
    947 { 
    948     // Handle SoLOD nodes specially 
    949     if (node->isOfType(SoLOD::getClassTypeId())) 
    950         return postLOD(data, action, node); 
    951  
    952 #ifdef DEBUG_IV_PLUGIN 
    953     osg::notify(osg::INFO) << "postGroup()   "  
    954               << node->getTypeId().getName().getString() << std::endl; 
    955 #endif 
    956     ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 
    957  
    958     // Pop all the groups that are Transforms 
    959     osg::ref_ptr<osg::Group> group = thisPtr->groupStack.top(); 
    960     while (strcmp(group->className(), "MatrixTransform") == 0) 
    961     { 
    962         thisPtr->groupStack.pop(); 
    963         group = thisPtr->groupStack.top(); 
    964     } 
    965  
    966     // Pop the group from the stack 
    967     thisPtr->groupStack.pop(); 
    968  
    969     // Pop the state if the group is a Separator 
    970     if (node->isOfType(SoSeparator::getClassTypeId())) 
    971     { 
    972         thisPtr->soTexStack.pop(); 
    973         thisPtr->lightStack.pop(); 
    974     } 
    975   
    976     return SoCallbackAction::CONTINUE; 
    977 } 
    978 //////////////////////////////////////////////////////////// 
    979 SoCallbackAction::Response  
    980 ConvertFromInventor::postLOD(void* data, SoCallbackAction *,  
    981                              const SoNode* node) 
    982 { 
    983 #ifdef DEBUG_IV_PLUGIN 
    984     osg::notify(osg::INFO) << "postLOD()    "  
    985               << node->getTypeId().getName().getString() << std::endl; 
    986 #endif 
    987  
    988     ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 
    989  
    990     // Inventor and OSG LOD node 
    991     SoLOD *ivLOD = (SoLOD *) node; 
    992     osg::LOD *lod = dynamic_cast<osg::LOD*>(thisPtr->groupStack.top()); 
    993  
    994     // Get the center of LOD and set it 
    995     SbVec3f ivCenter = ivLOD->center.getValue(); 
    996     lod->setCenter(osg::Vec3(ivCenter[0], ivCenter[1], ivCenter[2])); 
    997  
    998     // Verify the number of children and range values 
    999     int num = thisPtr->groupStack.top()->getNumChildren(); 
    1000     if (ivLOD->range.getNum()+1 != num && !(num == 0 && ivLOD->range.getNum() == 0)) { 
    1001         osg::notify(osg::WARN) << "IV import warning: SoLOD does not " 
    1002             << "contain correct data in range field." << std::endl; 
    1003         if (ivLOD->range.getNum()+1 < num) { 
    1004             thisPtr->groupStack.top()->removeChildren(ivLOD->range.getNum() + 1, 
    1005                                                       num - ivLOD->range.getNum() - 1); 
    1006             num = ivLOD->range.getNum() + 1; 
    1007         } 
    1008     } 
    1009  
    1010     // Get the ranges and set it 
    1011     if (num > 0) { 
    1012         if (num == 1) 
    1013             lod->setRange(0, 0.0, FLT_MAX); 
    1014         else { 
    1015             lod->setRange(0, 0.0, ivLOD->range[0]); 
    1016             for (int i = 1; i < num-2; i++) 
    1017                 lod->setRange(i, ivLOD->range[i-1], ivLOD->range[i]); 
    1018             lod->setRange(num-1, ivLOD->range[num-2], FLT_MAX); 
    1019         } 
    1020     } 
    1021  
    1022     // Pop the group from the stack 
    1023     thisPtr->groupStack.pop(); 
    1024  
    1025     return SoCallbackAction::CONTINUE; 
    1026 } 
    10271653///////////////////////////////////////////////////////////// 
    1028 SoCallbackAction::Response  
    1029 ConvertFromInventor::preRotor(void* data, SoCallbackAction *,  
    1030                               const SoNode* node) 
    1031 { 
    1032 #ifdef DEBUG_IV_PLUGIN 
    1033     osg::notify(osg::INFO) << "preRotor()  "  
     1654SoCallbackAction::Response 
     1655ConvertFromInventor::preRotor(void *data, SoCallbackAction *action, 
     1656                              const SoNode *node) 
     1657{ 
     1658#ifdef DEBUG_IV_PLUGIN 
     1659    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preRotor()  " 
    10341660              << node->getTypeId().getName().getString() << std::endl; 
    10351661#endif 
     
    10451671    // Create a new osg::MatrixTransform 
    10461672    osg::ref_ptr<osg::MatrixTransform> rotorTransform = new osg::MatrixTransform; 
    1047      
     1673 
    10481674    // Create a Rotor Callback equivalent to the inventor Rotor 
    10491675    osg::Vec3 pivot(0, 0, 0); 
    10501676    osg::Vec3 axis(ivAxis[0], ivAxis[1], ivAxis[2]); 
    1051     osg::ref_ptr<osgUtil::TransformCallback> rotorCallback  
    1052         = new osgUtil::TransformCallback(pivot, axis,  
     1677    osg::ref_ptr<osgUtil::TransformCallback> rotorCallback 
     1678        = new osgUtil::TransformCallback(pivot, axis, 
    10531679                                         2 * osg::PI * ivRotor->speed.getValue()); 
    10541680 
    10551681    // Set the app callback 
    10561682    rotorTransform->setUpdateCallback(rotorCallback.get()); 
    1057      
    1058     // Push the rotor transform onto the group stack 
    1059     thisPtr->groupStack.top()->addChild(rotorTransform.get()); 
    1060     thisPtr->groupStack.push(rotorTransform.get()); 
    1061  
    1062     return SoCallbackAction::CONTINUE; 
     1683 
     1684    // Push the rotor onto the state stack 
     1685    thisPtr->ivPushState(action, node, 
     1686              IvStateItem::MULTI_POP | IvStateItem::UPDATE_STATE | 
     1687              IvStateItem::APPEND_AT_PUSH, rotorTransform.get()); 
     1688 
     1689    // Append initial rotation to the model matrix 
     1690    if (!ivRotor->rotation.isIgnored()) { 
     1691        SoModelMatrixElement::rotateBy(action->getState(), ivRotor, 
     1692                                       ivRotor->rotation.getValue()); 
     1693    } 
     1694 
     1695    // Don't do the traversal of the SoShuttle 
     1696    // since it was seen on Coin that is does not append just 
     1697    // initial shuttle position, but some interpolated one, 
     1698    // resulting in incorrect animation. 
     1699    return SoCallbackAction::PRUNE; 
    10631700} 
    10641701//////////////////////////////////////////////////////////////// 
    1065 SoCallbackAction::Response  
    1066 ConvertFromInventor::prePendulum(void* data, SoCallbackAction *,  
     1702SoCallbackAction::Response 
     1703ConvertFromInventor::prePendulum(void* data, SoCallbackAction *action, 
    10671704                                 const SoNode* node) 
    10681705{ 
    10691706#ifdef DEBUG_IV_PLUGIN 
    1070     osg::notify(osg::INFO) << "prePendulum()  "  
     1707    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "prePendulum()  " 
    10711708              << node->getTypeId().getName().getString() << std::endl; 
    10721709#endif 
     
    10801717    ivPendulum->rotation0.getValue(ivAxis0, startAngle); 
    10811718    ivPendulum->rotation1.getValue(ivAxis1, endAngle); 
     1719    ivAxis0.normalize(); 
     1720    ivAxis1.normalize(); 
     1721 
     1722    // Reverse axis and direction if required 
     1723    // Actually, this will produce correct results only when axis is 
     1724    // opposite to each other, and approximate results when nearly 
     1725    // opposite and garbage otherwise. 
     1726    if ((ivAxis0+ivAxis1).length() < 0.5 ) { 
     1727        ivAxis1 = -ivAxis1; 
     1728        endAngle = -endAngle; 
     1729    } 
    10821730 
    10831731    // Create a new osg::MatrixTransform 
    10841732    osg::ref_ptr<osg::MatrixTransform> pendulumTransform = new osg::MatrixTransform; 
    1085      
     1733 
    10861734    // Create a Pendulum Callback equivalent to the inventor Rotor 
    1087     osg::Vec3 axis(ivAxis0[0], ivAxis0[1], ivAxis0[2]); 
    1088     PendulumCallback* pendulumCallback  
     1735    // Use axis from of the bigger angle (to avoid lost axis when 
     1736    // angle is zero - see SbRotation and quaternion theory). 
     1737    osg::Vec3 axis; 
     1738    if (fabs(startAngle) > fabs(endAngle)) 
     1739        axis = osg::Vec3(ivAxis0[0], ivAxis0[1], ivAxis0[2]); 
     1740    else 
     1741        axis = osg::Vec3(ivAxis1[0], ivAxis1[1], ivAxis1[2]); 
     1742    PendulumCallback* pendulumCallback 
    10891743        = new PendulumCallback(axis, startAngle, endAngle, 
    10901744                               ivPendulum->speed.getValue()); 
     
    10921746    // Set the app callback 
    10931747    pendulumTransform->setUpdateCallback(pendulumCallback); 
    1094      
    1095     // Push the pendulum transform onto the group stack 
    1096     thisPtr->groupStack.top()->addChild(pendulumTransform.get()); 
    1097     thisPtr->groupStack.push(pendulumTransform.get()); 
    1098  
    1099     return SoCallbackAction::CONTINUE; 
     1748 
     1749    // Push the pendulum onto the state stack 
     1750    thisPtr->ivPushState(action, node, 
     1751              IvStateItem::MULTI_POP | IvStateItem::UPDATE_STATE | 
     1752              IvStateItem::APPEND_AT_PUSH, pendulumTransform.get()); 
     1753 
     1754    // Don't do the traversal of the SoShuttle 
     1755    // since it was seen on Coin that is does not append just 
     1756    // initial shuttle position, but some interpolated one, 
     1757    // resulting in incorrect animation. 
     1758    return SoCallbackAction::PRUNE; 
    11001759} 
    11011760//////////////////////////////////////////////////////////////// 
    1102 SoCallbackAction::Response  
    1103 ConvertFromInventor::preShuttle(void* data, SoCallbackAction *,  
     1761SoCallbackAction::Response 
     1762ConvertFromInventor::preShuttle(void* data, SoCallbackAction *action, 
    11041763                                const SoNode* node) 
    11051764{ 
    11061765#ifdef DEBUG_IV_PLUGIN 
    1107     osg::notify(osg::INFO) << "preShuttle()  "  
     1766    osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preShuttle()  " 
    11081767              << node->getTypeId().getName().getString() << std::endl; 
    11091768#endif 
     
    11191778    // Create a new osg::MatrixTransform 
    11201779    osg::ref_ptr<osg::MatrixTransform> shuttleTransform = new osg::MatrixTransform; 
    1121      
     1780 
    11221781    // Create a shuttle Callback equivalent to the inventor Rotor 
    11231782    osg::Vec3 startPos(ivStartPos[0], ivStartPos[1], ivStartPos[2]); 
    11241783    osg::Vec3 endPos(ivEndPos[0], ivEndPos[1], ivEndPos[2]); 
    1125     ShuttleCallback* shuttleCallback  
     1784    ShuttleCallback* shuttleCallback 
    11261785        = new ShuttleCallback(startPos, endPos, ivShuttle->speed.getValue()); 
    11271786 
    11281787    // Set the app callback 
    11291788    shuttleTransform->setUpdateCallback(shuttleCallback); 
    1130      
    1131     // Push the shuttle transform onto the group stack 
    1132     thisPtr->groupStack.top()->addChild(shuttleTransform.get()); 
    1133     thisPtr->groupStack.push(shuttleTransform.get()); 
    1134  
    1135     return SoCallbackAction::CONTINUE; 
     1789 
     1790    // Push the shuttle onto the state stack 
     1791    thisPtr->ivPushState(action, node, 
     1792              IvStateItem::MULTI_POP | IvStateItem::UPDATE_STATE | 
     1793              IvStateItem::APPEND_AT_PUSH, shuttleTransform.get()); 
     1794 
     1795    // Don't do the traversal of the SoShuttle 
     1796    // since it was seen on Coin that is does not append just 
     1797    // initial shuttle position, but some interpolated one, 
     1798    // resulting in incorrect animation. 
     1799    return SoCallbackAction::PRUNE; 
    11361800} 
    11371801//////////////////////////////////////////////////////////// 
    11381802void ConvertFromInventor::addVertex(SoCallbackAction* action, 
    1139                                     const SoPrimitiveVertex *v,  
     1803                                    const SoPrimitiveVertex *v, 
    11401804                                    int index) 
    11411805{ 
     
    11501814        (normalBinding == osg::Geometry::BIND_PER_PRIMITIVE && index == 0)) 
    11511815    { 
    1152         if (vertexOrder == CLOCKWISE) 
    1153             normals.push_back(osg::Vec3(-norm[0], -norm[1], -norm[2])); 
    1154         else 
     1816        // What is this? Why to invert normals at CLOCKWISE vertex ordering? 
     1817        // PCJohn 2009-12-13 
     1818        //if (vertexOrder == CLOCKWISE) 
     1819        //    normals.push_back(osg::Vec3(-norm[0], -norm[1], -norm[2])); 
     1820        //else 
    11551821            normals.push_back(osg::Vec3(norm[0], norm[1], norm[2])); 
    11561822    } 
     
    11591825            colorBinding == osg::Geometry::BIND_PER_PRIMITIVE) 
    11601826    { 
    1161         // Get the material/color  
     1827        // Get the material/color 
    11621828        SbColor ambient, diffuse, specular, emission; 
    11631829        float transparency, shininess; 
    1164         action->getMaterial(ambient, diffuse, specular, emission, shininess,  
     1830        action->getMaterial(ambient, diffuse, specular, emission, shininess, 
    11651831                            transparency, v->getMaterialIndex()); 
    11661832        if (colorBinding == osg::Geometry::BIND_PER_VERTEX) 
     
    11771843} 
    11781844//////////////////////////////////////////////////////////////////////////// 
    1179 void ConvertFromInventor::addMatrixTransform(const std::string& name, SbVec3f axis, float angle, SbVec3f center, SbVec3f trans, SbVec3f scale) 
    1180 { 
    1181     osg::Matrix mat; 
    1182     if (trans.length() != 0.0 || name != "") 
    1183     { 
    1184         mat.makeIdentity(); 
    1185         mat.setTrans(trans[0], trans[1], trans[2]); 
    1186         osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform(mat); 
    1187         if (name != "") { 
    1188             std::string name2 = name; 
    1189             name2 += "_t"; 
    1190             mt->setName(name2); 
    1191         } 
    1192         groupStack.top()->addChild(mt.get()); 
    1193         groupStack.push(mt.get()); 
    1194     } 
    1195  
    1196     if (center.length() != 0.0) { 
    1197         mat.makeIdentity(); 
    1198         mat.setTrans(center[0], center[1], center[2]); 
    1199         osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform(mat); 
    1200         groupStack.top()->addChild(mt.get()); 
    1201         groupStack.push(mt.get()); 
    1202     } 
    1203  
    1204     if (angle != 0.0 || name != "") 
    1205     { 
    1206         osg::Quat q(angle, osg::Vec3f(axis[0], axis[1], axis[2])); 
    1207         mat.makeIdentity(); 
    1208         mat.setRotate(q);  
    1209         osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform(mat); 
    1210         if (name != "") { 
    1211             std::string name2 = name; 
    1212             name2 += "_r"; 
    1213             mt->setName(name2); 
    1214         } 
    1215         groupStack.top()->addChild(mt.get()); 
    1216         groupStack.push(mt.get()); 
    1217     } 
    1218  
    1219     if (center.length() != 0.0) { 
    1220         center.negate(); 
    1221         mat.makeIdentity(); 
    1222         mat.setTrans(center[0], center[1], center[2]); 
    1223         osg::ref_ptr<osg::MatrixTransform>  mt = new osg::MatrixTransform(mat); 
    1224         groupStack.top()->addChild(mt.get()); 
    1225         groupStack.push(mt.get()); 
    1226     } 
    1227  
    1228     if (scale[0] != 1.0 || scale[1] != 1.0 || scale[2] != 1.0)    { 
    1229         mat.makeIdentity(); 
    1230         mat.makeScale(scale[0], scale[1], scale[2]); 
    1231         osg::ref_ptr<osg::MatrixTransform>  smt = new osg::MatrixTransform(mat); 
    1232         groupStack.top()->addChild(smt.get()); 
    1233         groupStack.push(smt.get()); 
    1234     } 
    1235 } 
    1236 //////////////////////////////////////////////////////////////////////////// 
    12371845void ConvertFromInventor::addTriangleCB(void* data, SoCallbackAction* action, 
    12381846                                        const SoPrimitiveVertex* v0, 
     
    12411849{ 
    12421850    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 
    1243      
     1851 
    12441852    switch (thisPtr->vertexOrder) 
    12451853    { 
  • OpenSceneGraph/trunk/src/osgPlugins/Inventor/ConvertFromInventor.h

    r9053 r11032  
    1111#include <vector> 
    1212#include <stack> 
     13#include <assert.h> 
    1314 
    1415class ConvertFromInventor 
     
    1819        ~ConvertFromInventor(); 
    1920 
     21        /// Conversts from IV to OSG scene graph 
    2022        osg::Node* convert(SoNode* rootIVNode); 
    2123 
     24        /** 
     25         * Preprocessing restructure the scene for the convertor 
     26         * to be able to convert some peculiar scene constructions. 
     27         * Resulting scene is geometrically equivalent to the source 
     28         * scene. The preprocessing is related to grouping nodes only 
     29         * (SoSeparator, SoGroup, SoLOD, SoSwitch,...) and their 
     30         * treatment with traversal state. 
     31         */ 
     32        void preprocess(SoNode *root); 
     33 
    2234    private: 
    2335 
    24         // Callback functions for converting inventor scene graph to osg  
     36        // Callback functions for converting inventor scene graph to osg 
    2537        // scene graph 
    2638 
     39        static SoCallbackAction::Response preNode(void* data, 
     40                                 SoCallbackAction* action, const SoNode* node); 
     41        static SoCallbackAction::Response postNode(void* data, 
     42                                 SoCallbackAction* action, const SoNode* node); 
     43        static SoCallbackAction::Response preTransformSeparator(void* data, 
     44                                 SoCallbackAction* action, const SoNode* node); 
     45        static SoCallbackAction::Response postTransformSeparator(void* data, 
     46                                 SoCallbackAction* action, const SoNode* node); 
     47        static SoCallbackAction::Response preLOD(void* data, 
     48                                 SoCallbackAction* action, const SoNode* node); 
     49        static SoCallbackAction::Response postLOD(void* data, 
     50                                 SoCallbackAction* action, const SoNode* node); 
    2751        static SoCallbackAction::Response preShape(void* data, 
    2852                                 SoCallbackAction* action, const SoNode* node); 
    2953        static SoCallbackAction::Response postShape(void* data, 
    3054                                 SoCallbackAction* action, const SoNode* node); 
    31         static SoCallbackAction::Response preGroup(void* data, 
    32                                  SoCallbackAction* action, const SoNode* node); 
    33         static SoCallbackAction::Response postGroup(void* data, 
    34                                  SoCallbackAction* action, const SoNode* node); 
    35         static SoCallbackAction::Response preTexture(void* data,  
    36                                  SoCallbackAction* action, const SoNode* node); 
    37         static SoCallbackAction::Response preLight(void* data,  
    38                                  SoCallbackAction* action, const SoNode* node); 
    39         static SoCallbackAction::Response preRotor(void* data,  
    40                                  SoCallbackAction* action, const SoNode* node); 
    41         static SoCallbackAction::Response prePendulum(void* data,  
    42                                  SoCallbackAction* action, const SoNode* node); 
    43         static SoCallbackAction::Response preShuttle(void* data,  
    44                                  SoCallbackAction* action, const SoNode* node); 
    45         static SoCallbackAction::Response postLOD(void* data, 
    46                                  SoCallbackAction* action, const SoNode* node); 
    47         ///Callback for VRMLImageTexture 
    48         ///\param data The pointer to ConvertFromInventor object 
    49         ///\param action The action handling class 
    50         ///\param node The current VRMLImageTexture node 
    51         static SoCallbackAction::Response preVRMLImageTexture(void* data, 
    52                                  SoCallbackAction* action, const SoNode* node); 
    53         static SoCallbackAction::Response preVRMLAppearance(void* data, 
    54                                  SoCallbackAction* action, const SoNode* node); 
    55         static SoCallbackAction::Response postVRMLAppearance(void* data, 
     55        static SoCallbackAction::Response postTexture(void* data, 
     56                                 SoCallbackAction* action, const SoNode* node); 
     57        static SoCallbackAction::Response preLight(void* data, 
     58                                 SoCallbackAction* action, const SoNode* node); 
     59        static SoCallbackAction::Response preEnvironment(void* data, 
     60                                 SoCallbackAction* action, const SoNode* node); 
     61        static SoCallbackAction::Response preShaderProgram(void* data, 
     62                                 SoCallbackAction* action, const SoNode* node); 
     63        static SoCallbackAction::Response preRotor(void* data, 
     64                                 SoCallbackAction* action, const SoNode* node); 
     65        static SoCallbackAction::Response prePendulum(void* data, 
     66                                 SoCallbackAction* action, const SoNode* node); 
     67        static SoCallbackAction::Response preShuttle(void* data, 
    5668                                 SoCallbackAction* action, const SoNode* node); 
    5769        static SoCallbackAction::Response preInfo(void* data, 
     
    6880                               const SoPrimitiveVertex *v0); 
    6981 
     82        static SoCallbackAction::Response restructure(void* data, 
     83                                 SoCallbackAction* action, const SoNode* node); 
     84        static SoCallbackAction::Response restructurePreNode(void* data, 
     85                                 SoCallbackAction* action, const SoNode* node); 
     86        static SoCallbackAction::Response restructurePostNode(void* data, 
     87                                 SoCallbackAction* action, const SoNode* node); 
     88 
    7089    private: 
    7190        SbString transformInfoName; 
    7291        SbName appearanceName; 
    73         bool inAppearanceWithNoTexture; 
    74  
    75         void addMatrixTransform(const std::string& name, SbVec3f axis, float angle, SbVec3f center, SbVec3f trans, SbVec3f scale); 
    76         void addVertex(SoCallbackAction* action, const SoPrimitiveVertex* v,  
     92 
     93        void addVertex(SoCallbackAction* action, const SoPrimitiveVertex* v, 
    7794                       int index); 
    7895 
    7996        osg::ref_ptr<osg::StateSet> getStateSet(SoCallbackAction* action); 
    8097 
    81         osg::Texture2D* convertIVTexToOSGTex(const SoNode* soNode,  
     98        osg::Texture2D* convertIVTexToOSGTex(const SoNode* soNode, 
    8299                                             SoCallbackAction* action); 
    83100 
     
    100117        std::vector<osg::Vec2> textureCoords; 
    101118 
    102         // Num of primitive and primitive type  
     119        // Num of primitive and primitive type 
    103120        int numPrimitives; 
    104121        osg::PrimitiveSet::Mode primitiveType; 
     
    108125        VertexOrder vertexOrder; 
    109126 
    110         // Stack of group nodes (used to build the scene graph) 
    111         std::stack<osg::Group* > groupStack; 
    112         // Stack of texture nodes (used for attaching the right texture to the 
    113         // geosets). Supported types are SoTexture2 and SoVRMLImageTexture for now. 
    114         std::stack<const SoNode*> soTexStack; 
    115  
    116127        // Mapping from SoTexture2 and SoVRMLImageTexture to already converted 
    117128        // osg::Texture2D - avoids duplication of same texture objects 
    118129        std::map<const SoNode*, osg::Texture2D*> ivToOsgTexMap; 
    119130 
    120         // Stack to maintain the list of lights at each level of the  
    121         // scenegraph 
    122         typedef std::vector<osg::Light *> LightList; 
    123         std::stack<LightList> lightStack; 
    124  
    125131        osg::ref_ptr<osg::MatrixTransform> _root;///<The root node; 
    126132 
    127         osg::ref_ptr<osg::Group> lightGroup; 
     133        /** 
     134         * IvStateItem aids lack of some state retrieval methods 
     135         * of SoCallbackAction. State is maintained in stack 
     136         * manner separately from Open Inventor. 
     137         */ 
     138        class IvStateItem { 
     139        public: 
     140 
     141            // Pop flags and node caused the push 
     142            enum Flags { 
     143                DEFAULT_FLAGS = 0, 
     144                MULTI_POP = 1, 
     145                KEEP_CHILDREN_ORDER = 2, 
     146                APPEND_AT_PUSH = 4, 
     147                UPDATE_STATE = 8, 
     148                UPDATE_STATE_EXCEPT_TRANSFORM = 0x10 // this has the same 
     149                          // effect as UPDATE_STATE at the present time 
     150            }; 
     151            int flags; 
     152            const SoNode *pushInitiator; 
     153 
     154            // Tracking of model transformation 
     155            SbMatrix inheritedTransformation; 
     156            SbMatrix lastUsedTransformation; 
     157 
     158            // Active texture node (used for attaching the right texture to the 
     159            // geosets). Supported types are SoTexture2 and SoVRMLImageTexture for now. 
     160            // No multitexturing yet. 
     161            const SoNode* inheritedTexture; 
     162            const SoNode* currentTexture; 
     163 
     164            // List of active lights 
     165            std::vector<osg::ref_ptr<osg::Light> > inheritedLights; 
     166            std::vector<osg::ref_ptr<osg::Light> > currentLights; 
     167 
     168            // Active OpenGL glProgram and associated shaders 
     169            osg::ref_ptr<osg::Program> inheritedGLProgram; 
     170            osg::ref_ptr<osg::Program> currentGLProgram; 
     171 
     172            // Ambient light (of SoEnvironment) 
     173            SbColor inheritedAmbientLight; 
     174            SbColor currentAmbientLight; 
     175 
     176            // Generated OSG graph 
     177            osg::ref_ptr<osg::Group> osgStateRoot; 
     178 
     179            // Extra variables 
     180            const SoNode *keepChildrenOrderParent; 
     181 
     182            IvStateItem(const SoNode *initiator, osg::Group *root = NULL) : 
     183                flags(IvStateItem::DEFAULT_FLAGS), 
     184                pushInitiator(initiator), 
     185                inheritedTransformation(SbMatrix::identity()), 
     186                lastUsedTransformation(SbMatrix::identity()), 
     187                inheritedTexture(NULL), 
     188                currentTexture(NULL), 
     189                inheritedLights(), 
     190                currentLights(), 
     191                inheritedGLProgram(NULL), 
     192                currentGLProgram(NULL), 
     193                inheritedAmbientLight(SbColor(0.2f,0.2f,0.2f)), 
     194                currentAmbientLight(SbColor(0.2f,0.2f,0.2f)), 
     195                osgStateRoot(root ? root : new osg::Group) {} 
     196 
     197            IvStateItem(const IvStateItem& i, const SoCallbackAction *action, 
     198                        const SoNode *initiator, const int f, 
     199                        osg::Group *root) : 
     200                flags(f), 
     201                pushInitiator(initiator), 
     202                inheritedTransformation(action->getModelMatrix()), 
     203                lastUsedTransformation(action->getModelMatrix()), 
     204                inheritedTexture(i.currentTexture), 
     205                currentTexture(i.currentTexture), 
     206                inheritedLights(i.currentLights), 
     207                currentLights(i.currentLights), 
     208                inheritedGLProgram(i.currentGLProgram), 
     209                currentGLProgram(i.currentGLProgram), 
     210                inheritedAmbientLight(i.inheritedAmbientLight), 
     211                currentAmbientLight(i.currentAmbientLight), 
     212                osgStateRoot(root) {} 
     213        }; 
     214 
     215        /// State stack for Inventor scene traversal 
     216        std::stack<IvStateItem> ivStateStack; 
     217 
     218        void ivPushState(const SoCallbackAction *action, 
     219                         const SoNode *initiator, const int flags = IvStateItem::DEFAULT_FLAGS, 
     220                         osg::Group *root = new osg::Group); 
     221        void ivPopState(const SoCallbackAction *action, const SoNode *initator); 
     222 
     223        void appendNode(osg::Node *n, const SoCallbackAction *action); 
     224 
    128225}; 
    129226 
  • OpenSceneGraph/trunk/src/osgPlugins/Inventor/ConvertToInventor.cpp

    r9414 r11032  
    237237    for (i=0, z=0; i<num; i++) 
    238238      if (z == numItemsUntilMinusOne) { 
    239         a[i] = -1; 
     239        a[i] = ivType(-1); 
    240240        z = 0; 
    241241      } else { 
     
    19211921      // Note: use SoTransform instead of SoRotation because SoRotation is not supported by VRML1. 
    19221922      SoTransform *transform = new SoTransform; 
    1923       transform->rotation = SbRotation(SbVec3f(1.f,0.f,0.f), -M_PI_2); 
     1923      transform->rotation = SbRotation(SbVec3f(1.f,0.f,0.f), float(-M_PI_2)); 
    19241924 
    19251925      SoSeparator *separator = new SoSeparator; 
     
    20482048  popInventorState(); 
    20492049} 
     2050 
  • OpenSceneGraph/trunk/src/osgPlugins/Inventor/PendulumCallback.cpp

    r6051 r11032  
    33#include "PendulumCallback.h" 
    44 
    5 PendulumCallback::PendulumCallback(const osg::Vec3& axis,  
     5PendulumCallback::PendulumCallback(const osg::Vec3& axis, 
    66                                         float startAngle, float endAngle, 
    77                                         float frequency) 
     
    1111    _endAngle = endAngle; 
    1212    _frequency = frequency; 
    13      
     13 
    1414    _previousTraversalNumber = -1; 
    1515    _previousTime = -1.0; 
     
    2727 
    2828    const osg::FrameStamp* fs = nv->getFrameStamp(); 
    29     if (!fs)  
    30         return;  
    31      
     29    if (!fs) 
     30        return; 
     31 
    3232    // ensure that we do not operate on this node more than 
    3333    // once during this traversal.  This is an issue since node 
     
    3636    { 
    3737        double currentTime = fs->getSimulationTime(); 
     38        if (_previousTime == -1.) 
     39            _previousTime = currentTime; 
    3840        _angle += (currentTime - _previousTime) * 2 * osg::PI * _frequency; 
    39          
    40         double frac = 0.5 + 0.5 * sin(_angle); 
    41         double rotAngle = _endAngle  - _startAngle - osg::PI  
     41 
     42        double frac = 0.5 - 0.5 * cos(_angle); 
     43        double rotAngle = //_endAngle  - _startAngle - osg::PI 
    4244                + (1.0 - frac) * _startAngle + frac * _endAngle; 
    4345 
    4446        // update the specified transform 
    4547        transform->setMatrix(osg::Matrix::rotate(rotAngle, _axis)); 
    46              
     48 
    4749        _previousTraversalNumber = nv->getTraversalNumber(); 
    4850        _previousTime = currentTime; 
     
    5355 
    5456} 
     57 
  • OpenSceneGraph/trunk/src/osgPlugins/Inventor/README.txt

    r7348 r11032  
    1818 
    1919- Coin - GPL, support of VRML 2.0 
    20   (http://www.coin3d.org)  
     20  (http://www.coin3d.org) 
    2121- SGI Inventor - LGPL 
    2222  (http://oss.sgi.com/projects/inventor/) 
     
    2727Contributors: 
    2828 
    29 Sean Spicer - Vivek (c) Magic-Earth - Original author of the plugin 
     29Sean Spicer - Vivek (c) Magic-Earth - Original author of the Inventor reader 
    3030Gerrick Bivins 
    31 PCJohn - Jan Peciva, Cadwork (c) 
     31PCJohn - Jan Peciva, Cadwork (c) - author of Inventor writer, number of 
     32                                   contributions and improvements to the reader 
    3233 
    3334Minor fixes: 
  • OpenSceneGraph/trunk/src/osgPlugins/Inventor/ReaderWriterIV.cpp

    r8578 r11032  
    1 #include "ReaderWriterIV.h" 
    2  
    31// OSG headers 
    42#include <osg/Notify> 
     
    1311#include <Inventor/actions/SoWriteAction.h> 
    1412#include <Inventor/actions/SoCallbackAction.h> 
    15  
    1613#ifdef __COIN__ 
    17 #include <Inventor/VRMLnodes/SoVRMLImageTexture.h> 
     14# include <Inventor/VRMLnodes/SoVRMLImageTexture.h> 
    1815#endif 
    1916 
     17#include "ReaderWriterIV.h" 
    2018#include "ConvertFromInventor.h" 
    21 #include "GroupSoLOD.h" 
    2219#include "ConvertToInventor.h" 
     20 
     21// forward declarations of static functions 
     22static void addSearchPaths(const osgDB::FilePathList *searchPaths); 
     23static void removeSearchPaths(const osgDB::FilePathList *searchPaths); 
    2324 
    2425 
     
    2627REGISTER_OSGPLUGIN(Inventor, ReaderWriterIV) 
    2728 
     29 
     30/** 
     31 * Constructor. 
     32 * Initializes the ReaderWriterIV. 
     33 */ 
    2834ReaderWriterIV::ReaderWriterIV() 
    2935{ 
     36    // Set supported extensions and options 
    3037    supportsExtension("iv","Inventor format"); 
    3138    supportsExtension("wrl","VRML world file"); 
    32 } 
    33  
    34 // Read file and convert to OSG 
    35 osgDB::ReaderWriter::ReadResult  
    36 ReaderWriterIV::readNode(const std::string& file, 
    37                          const osgDB::ReaderWriter::Options* options) const 
    38 { 
    39     std::string ext = osgDB::getLowerCaseFileExtension(file); 
    40     if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; 
    41  
    42     std::string fileName = osgDB::findDataFile( file, options ); 
    43     if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; 
    44  
    45     osg::notify(osg::INFO) << "osgDB::ReaderWriterIV::readNode() Reading file "  
    46                            << fileName.data() << std::endl; 
    47      
     39 
     40    // Initialize Inventor 
     41    initInventor(); 
     42} 
     43 
     44 
     45/** 
     46 * Initializes Open Inventor. 
     47 */ 
     48void ReaderWriterIV::initInventor() const 
     49{ 
    4850    // Initialize Inventor 
    4951    SoDB::init(); 
    5052    SoNodeKit::init(); 
    5153    SoInteraction::init(); 
    52      
    53  
    54     // Initial GroupSoLOD node 
    55     GroupSoLOD::initClass(); 
    5654 
    5755#ifdef __COIN__ 
     
    5957    SoVRMLImageTexture::setDelayFetchURL(FALSE); 
    6058#endif 
     59} 
     60 
     61 
     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 
     76    SoSeparator* rootIVNode = SoDB::readAll(&input); 
     77 
     78    // Remove recently appened search paths 
     79    if (options) 
     80        removeSearchPaths(searchPaths); 
     81 
     82    // Close the file 
     83    input.closeFile(); 
     84 
     85    // Perform conversion 
     86    ReadResult result; 
     87    if (rootIVNode) 
     88    { 
     89        rootIVNode->ref(); 
     90        // Convert the inventor scenegraph to an osg scenegraph 
     91        ConvertFromInventor convertIV; 
     92        convertIV.preprocess(rootIVNode); 
     93        result = convertIV.convert(rootIVNode); 
     94        rootIVNode->unref(); 
     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; 
     115    } 
     116 
     117    return result; 
     118} 
     119 
     120 
     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; 
    61139 
    62140    // Open the file 
     
    69147    } 
    70148 
    71     // Create the inventor scenegraph from the file 
    72     SoSeparator* rootIVNode = SoDB::readAll(&input); 
    73  
    74     // Close the file 
    75     input.closeFile(); 
    76  
    77     if (rootIVNode) 
    78     { 
    79         rootIVNode->ref(); 
    80         // Convert the inventor scenegraph to an osg scenegraph and return it 
    81         ConvertFromInventor convertIV; 
    82         ReadResult result = convertIV.convert(rootIVNode); 
    83         rootIVNode->unref(); 
    84         return result; 
     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        } 
    85189    } 
    86  
    87     return ReadResult::FILE_NOT_HANDLED; 
     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; 
    88202} 
    89203 
     
    98212    bool useVRML1 = !isInventorExtension(osgDB::getFileExtension(fileName)); 
    99213 
    100     osg::notify(osg::INFO) << "osgDB::ReaderWriterIV::writeNode() Writing file "  
    101                            << fileName.data() << std::endl; 
    102      
    103     // Initialize Inventor 
    104     SoInteraction::init(); 
     214    osg::notify(osg::NOTICE) << "osgDB::ReaderWriterIV::writeNode() Writing file " 
     215                             << fileName.data() << std::endl; 
    105216 
    106217    // Convert OSG graph to Inventor graph 
     
    131242    return WriteResult::FILE_SAVED; 
    132243} 
     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} 
     258 
  • OpenSceneGraph/trunk/src/osgPlugins/Inventor/ReaderWriterIV.h

    r8578 r11032  
    99    public: 
    1010        ReaderWriterIV(); 
    11          
     11 
    1212        virtual const char* className() const 
    13         {  
    14             return "Inventor reader/writer";  
     13        { 
     14            return "Inventor reader/writer"; 
    1515        } 
    16          
     16 
    1717        bool isInventorExtension(const std::string& extension) const 
    1818        { 
     
    2020        } 
    2121 
    22         virtual ReadResult readNode(const std::string& filename,  
    23                                     const osgDB::ReaderWriter::Options *) const; 
     22        virtual ReadResult readNode(const std::string& filename, 
     23                                    const osgDB::ReaderWriter::Options*) const; 
     24        virtual ReadResult readNode(std::istream& fin, 
     25                                    const osgDB::ReaderWriter::Options* = NULL) const; 
     26 
    2427 
    2528        virtual WriteResult writeNode(const osg::Node& node, const std::string& filename, 
    2629                                      const osgDB::ReaderWriter::Options* options = NULL) const; 
     30 
     31    protected: 
     32        void initInventor() const; 
     33        ReadResult readNodeFromSoInput(class SoInput&, 
     34                  std::string &fileName, const osgDB::ReaderWriter::Options*) const; 
    2735}; 
    2836 
    2937#endif 
     38 
  • OpenSceneGraph/trunk/src/osgPlugins/Inventor/ShuttleCallback.cpp

    r6051 r11032  
    33#include "ShuttleCallback.h" 
    44 
    5 ShuttleCallback::ShuttleCallback(const osg::Vec3& startPos,  
     5ShuttleCallback::ShuttleCallback(const osg::Vec3& startPos, 
    66                                 const osg::Vec3& endPos, 
    77                                 float frequency) 
     
    1010    _endPos = endPos; 
    1111    _frequency = frequency; 
    12      
     12 
    1313    _previousTraversalNumber = -1; 
    1414    _previousTime = -1.0; 
     
    2626 
    2727    const osg::FrameStamp* fs = nv->getFrameStamp(); 
    28     if (!fs)  
    29         return;  
    30      
     28    if (!fs) 
     29        return; 
     30 
    3131    // ensure that we do not operate on this node more than 
    3232    // once during this traversal.  This is an issue since node 
     
    3535    { 
    3636        double currentTime = fs->getSimulationTime(); 
     37        if (_previousTime == -1.) 
     38            _previousTime = currentTime; 
    3739        _angle += (currentTime - _previousTime) * 2 * osg::PI * _frequency; 
    38          
    39         double frac = 0.5 + 0.5 * sin(_angle); 
     40 
     41        double frac = 0.5 - 0.5 * cos(_angle); 
    4042 
    4143        osg::Vec3 position = _startPos * (1.0 - frac) + _endPos * frac; 
     
    4345        // update the specified transform 
    4446        transform->setMatrix(osg::Matrix::translate(position)); 
    45              
     47 
    4648        _previousTraversalNumber = nv->getTraversalNumber(); 
    4749        _previousTime = currentTime; 
     
    5254 
    5355} 
     56