root/OpenSceneGraph/trunk/src/osgPlugins/Inventor/ConvertFromInventor.cpp @ 9585

Revision 9585, 46.8 kB (checked in by robert, 6 years ago)

Fixed warning

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[2225]1#include "ConvertFromInventor.h"
[6419]2
[2225]3#include "PendulumCallback.h"
4#include "ShuttleCallback.h"
5
6// OSG headers
7#include <osg/MatrixTransform>
[5802]8#include <osg/Node>
[2225]9#include <osg/Geode>
10#include <osg/Notify>
11#include <osg/LineWidth>
12#include <osg/Point>
13#include <osg/TexEnv>
14#include <osg/Texture2D>
15#include <osg/PolygonMode>
16#include <osg/BlendFunc>
17#include <osg/Material>
18#include <osg/CullFace>
19#include <osg/LightModel>
[9053]20#include <osg/LightSource>
[5802]21#include <osg/ShadeModel>
[2225]22#include <osg/LOD>
23#include <osgUtil/TransformCallback>
24
25// Inventor headers
26#include <Inventor/SoDB.h>
27#include <Inventor/SoInteraction.h>
28#include <Inventor/nodes/SoSeparator.h>
29#include <Inventor/nodes/SoShape.h>
30#include <Inventor/nodes/SoVertexShape.h>
31#include <Inventor/nodes/SoLight.h>
32#include <Inventor/nodes/SoDirectionalLight.h>
33#include <Inventor/nodes/SoSpotLight.h>
34#include <Inventor/nodes/SoPointLight.h>
35#include <Inventor/nodes/SoRotor.h>
36#include <Inventor/nodes/SoPendulum.h>
37#include <Inventor/nodes/SoShuttle.h>
38#include <Inventor/nodes/SoLOD.h>
[6543]39#include <Inventor/nodes/SoTexture2.h>
[2225]40#include <Inventor/misc/SoChildList.h>
41#include <Inventor/SoPrimitiveVertex.h>
42#include <Inventor/SbLinear.h>
[9053]43#include <Inventor/nodes/SoTransform.h>
44#include <Inventor/nodes/SoInfo.h>
[2225]45
[7348]46#ifdef __COIN__
[6544]47#include <Inventor/VRMLnodes/SoVRMLImageTexture.h>
[9053]48#include <Inventor/VRMLnodes/SoVRMLTransform.h>
49#include <Inventor/VRMLnodes/SoVRMLAppearance.h>
50#include <Inventor/VRMLnodes/SoVRMLMaterial.h>
[6544]51#endif
52
[2225]53#include "GroupSoLOD.h"
54
55#include <map>
[6544]56#include <assert.h>
[2225]57#include <math.h>
[9053]58#include <string.h>
[2225]59#ifdef __linux
60#include <values.h>
61#endif
62#ifdef __APPLE__
63#include <float.h>
64#endif
65
[3920]66#define DEBUG_IV_PLUGIN
[5802]67///////////////////////////////////////////
[2225]68ConvertFromInventor::ConvertFromInventor()
69{
70    numPrimitives = 0;
[9053]71    transformInfoName = "";
72    appearanceName = "";
73    inAppearanceWithNoTexture = false;
74    lightGroup = NULL;
[2225]75}
[5802]76///////////////////////////////////////////
[2225]77ConvertFromInventor::~ConvertFromInventor()
78{
79}
[5802]80///////////////////////////////////////////////////////////
[2225]81osg::Node* ConvertFromInventor::convert(SoNode* rootIVNode)
82{   
83    // Transformation matrix for converting Inventor coordinate system to OSG
84    // coordinate system
[6543]85    osg::Matrix ivToOSGMat(osg::Matrix(1.0, 0.0, 0.0, 0.0,
[2225]86                                       0.0, 0.0, 1.0, 0.0,
87                                       0.0,-1.0, 0.0, 0.0,
88                                       0.0, 0.0, 0.0, 1.0));
89
90    // Create a root node and push it onto the stack
[5802]91    _root = new osg::MatrixTransform;
92    _root->setMatrix(ivToOSGMat);
93    groupStack.push(_root.get());
[2225]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
100    // These callback functions perform the conversion
[6543]101    // note: if one class is derived from the other and both callbacks
102    // are registered, both functions will be called
[2225]103    SoCallbackAction cbAction;
104    cbAction.addPreCallback(SoShape::getClassTypeId(), preShape, this);
105    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);
[7348]109#ifdef __COIN__
[6543]110    cbAction.addPreCallback(SoVRMLImageTexture::getClassTypeId(),
111                            preVRMLImageTexture, this);
[9053]112    cbAction.addPreCallback(SoVRMLAppearance::getClassTypeId(),
113                            preVRMLAppearance, this);
114    cbAction.addPreCallback(SoInfo::getClassTypeId(), preInfo, this);
[6544]115#endif
[2225]116    cbAction.addPreCallback(SoLight::getClassTypeId(), preLight, this);
117    cbAction.addPreCallback(SoRotor::getClassTypeId(), preRotor, this);
118    cbAction.addPreCallback(SoPendulum::getClassTypeId(), prePendulum, this);
119    cbAction.addPreCallback(SoShuttle::getClassTypeId(), preShuttle, this);
120    cbAction.addTriangleCallback(SoShape::getClassTypeId(), addTriangleCB, this);
121    cbAction.addLineSegmentCallback(SoShape::getClassTypeId(), addLineSegmentCB,
122                                    this);
123    cbAction.addPointCallback(SoShape::getClassTypeId(), addPointCB, this);
[6543]124
[2225]125    // Traverse the inventor scene graph
126    cbAction.apply(rootIVNode);
127
[6543]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.");
[2225]140
[6543]141    assert(soTexStack.size() == 0 && "soTexStack was left at inconsistent state.");
142
143    assert(lightStack.size() == 1 && "lightStack was left at inconsistent state.");
[2225]144    lightStack.pop();
145
[5802]146    return _root.get();
[2225]147}
[5802]148///////////////////////////////////////////////////////////////////
[2225]149SoCallbackAction::Response
150ConvertFromInventor::preShape(void* data, SoCallbackAction* action,
151                              const SoNode* node)
152{
153#ifdef DEBUG_IV_PLUGIN
[2896]154    osg::notify(osg::INFO) << "preShape()    " 
[2225]155              << node->getTypeId().getName().getString() << std::endl;
156#endif
157
158    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
159
160    // Normal and color binding map from Inventor to OSG
161    static std::map<SoNormalBinding::Binding, osg::Geometry::AttributeBinding>
162        normBindingMap;
163    static std::map<SoMaterialBinding::Binding, osg::Geometry::AttributeBinding>
164        colBindingMap;
165    static bool firstTime = true;
166    if (firstTime)
167    {
168        normBindingMap[SoNormalBinding::OVERALL] 
169                                        = osg::Geometry::BIND_OVERALL;
170        normBindingMap[SoNormalBinding::PER_PART]
171                                        = osg::Geometry::BIND_PER_PRIMITIVE;
172        normBindingMap[SoNormalBinding::PER_PART_INDEXED]
173                                        = osg::Geometry::BIND_PER_PRIMITIVE;
174        normBindingMap[SoNormalBinding::PER_FACE]
175                                        = osg::Geometry::BIND_PER_PRIMITIVE;
176        normBindingMap[SoNormalBinding::PER_FACE_INDEXED]
177                                        = osg::Geometry::BIND_PER_PRIMITIVE;
178        normBindingMap[SoNormalBinding::PER_VERTEX]
179                                        = osg::Geometry::BIND_PER_VERTEX;
180        normBindingMap[SoNormalBinding::PER_VERTEX_INDEXED]
181                                        = osg::Geometry::BIND_PER_VERTEX;
182
183        colBindingMap[SoMaterialBinding::OVERALL]
184                                        = osg::Geometry::BIND_OVERALL;
185        colBindingMap[SoMaterialBinding::PER_PART]
186                                        = osg::Geometry::BIND_PER_PRIMITIVE;
187        colBindingMap[SoMaterialBinding::PER_PART_INDEXED]
188                                        = osg::Geometry::BIND_PER_PRIMITIVE;
189        colBindingMap[SoMaterialBinding::PER_FACE]
190                                        = osg::Geometry::BIND_PER_PRIMITIVE;
191        colBindingMap[SoMaterialBinding::PER_FACE_INDEXED]
192                                        = osg::Geometry::BIND_PER_PRIMITIVE;
193        colBindingMap[SoMaterialBinding::PER_VERTEX]
194                                        = osg::Geometry::BIND_PER_VERTEX;
195        colBindingMap[SoMaterialBinding::PER_VERTEX_INDEXED]
196                                        = osg::Geometry::BIND_PER_VERTEX;
197
198        firstTime = false;
199    }
200
201    // Get normal and color binding
202    if (node->isOfType(SoVertexShape::getClassTypeId()))
203    {
204        thisPtr->normalBinding = normBindingMap[action->getNormalBinding()];
205        thisPtr->colorBinding = colBindingMap[action->getMaterialBinding()];
206    }
207    else
208    {
209        thisPtr->normalBinding = osg::Geometry::BIND_PER_VERTEX;
210        thisPtr->colorBinding = osg::Geometry::BIND_PER_VERTEX;
211    }
212
213    // Check vertex ordering
214    if (action->getVertexOrdering() == SoShapeHints::CLOCKWISE)
215        thisPtr->vertexOrder = CLOCKWISE;
216    else
217        thisPtr->vertexOrder = COUNTER_CLOCKWISE;
218
219    // Clear the data from the previous shape callback
220    thisPtr->numPrimitives = 0;
221    thisPtr->vertices.clear();
222    thisPtr->normals.clear();
223    thisPtr->colors.clear();
224    thisPtr->textureCoords.clear();
225   
226    return SoCallbackAction::CONTINUE;
227}
[5802]228///////////////////////////////////////////////////////////
229// OSG doesn't seem to have a transpose function         //
230//for matrices                                           //
231///////////////////////////////////////////////////////////
[2225]232void ConvertFromInventor::transposeMatrix(osg::Matrix& mat)
233{
234    float tmp;
235    for (int j = 0; j < 4; j++)
236    {
237        for (int i = j + 1; i < 4; i++)
238        {
239            tmp = mat.operator()(j,i);
240            mat.operator()(j,i) = mat.operator()(i,j);
241            mat.operator()(i,j) = tmp;
242        }
243    }
244
245}
[5802]246////////////////////////////////////////////////////////////////////
[2225]247SoCallbackAction::Response
248ConvertFromInventor::postShape(void* data, SoCallbackAction* action,
[3920]249                               const SoNode* node)
[2225]250{
251#ifdef DEBUG_IV_PLUGIN
[2896]252    osg::notify(osg::INFO) << "postShape()   "
[2225]253              << node->getTypeId().getName().getString() << std::endl;
254#endif
255
256    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
257
[3920]258
259    // Create a new Geometry
[5802]260    osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
[3920]261
[2225]262
[5802]263    osg::ref_ptr<osg::Vec3Array> coords = new osg::Vec3Array(thisPtr->vertices.size());
[2225]264    for (unsigned int i = 0; i < thisPtr->vertices.size(); i++)
[9053]265        (*coords)[i] = thisPtr->vertices[i];
[5802]266    geometry->setVertexArray(coords.get());
[3920]267
[5802]268    osg::ref_ptr<osg::Vec3Array> norms = NULL;
[2225]269    if (thisPtr->normalBinding == osg::Geometry::BIND_OVERALL)
270    {
271        norms = new osg::Vec3Array(1);
272        const SbVec3f &norm = action->getNormal(0);
273        (*norms)[0].set(norm[0], norm[1], norm[2]);
274    }
275    else
276    {
277        norms = new osg::Vec3Array(thisPtr->normals.size());
278        for (unsigned int i = 0; i < thisPtr->normals.size(); i++)
279        {
[9053]280            (*norms)[i] = thisPtr->normals[i];
[2225]281        }
282    }
[5802]283    geometry->setNormalArray(norms.get());
[3920]284    geometry->setNormalBinding(thisPtr->normalBinding);
[2225]285
286    // Set the colors
[5802]287    osg::ref_ptr<osg::Vec4Array> cols;
[2225]288    if (thisPtr->colorBinding == osg::Geometry::BIND_OVERALL)
289    {
290        cols = new osg::Vec4Array(1);
291        SbColor ambient, diffuse, specular, emission;
292        float transparency, shininess;
293        action->getMaterial(ambient, diffuse, specular, emission, shininess,
294                            transparency, 0);
295        (*cols)[0].set(diffuse[0], diffuse[1], diffuse[2], 1.0 - transparency);
296    }
297    else
298    {
299        cols = new osg::Vec4Array(thisPtr->colors.size());
300        for (unsigned int i = 0; i < thisPtr->colors.size(); i++)
301            (*cols)[i] = thisPtr->colors[i];
302    }
[5802]303    geometry->setColorArray(cols.get());
[3920]304    geometry->setColorBinding(thisPtr->colorBinding);
[2225]305
306
[5802]307    if (thisPtr->textureCoords.empty())
[6543]308        osg::notify(osg::INFO)<<"tex coords not found"<<std::endl;
[5802]309    else {
310       
311        // report texture coordinate conditions
312        if (action->getNumTextureCoordinates()>0)
[6543]313            osg::notify(osg::INFO)<<"tex coords found"<<std::endl;
[5802]314        else
[6543]315           osg::notify(osg::INFO)<<"tex coords generated"<<std::endl;
[5802]316
[3920]317        // Get the texture transformation matrix
318        osg::Matrix textureMat;
319        textureMat.set((float *) action->getTextureMatrix().getValue());
320
321        // Transform texture coordinates if texture matrix is not an identity mat
[5802]322        osg::Matrix identityMat;
323        identityMat.makeIdentity();
324        osg::ref_ptr<osg::Vec2Array> texCoords
[3920]325            = new osg::Vec2Array(thisPtr->textureCoords.size());
[5802]326        if (textureMat == identityMat)
[2225]327        {
[3920]328            // Set the texture coordinates
329            for (unsigned int i = 0; i < thisPtr->textureCoords.size(); i++)
330                (*texCoords)[i] = thisPtr->textureCoords[i];
[2225]331        }
[3920]332        else
333        {
334            // Transform and set the texture coordinates
335            for (unsigned int i = 0; i < thisPtr->textureCoords.size(); i++)
336            {
337                osg::Vec3 transVec = textureMat.preMult(
338                        osg::Vec3(thisPtr->textureCoords[i][0],
339                                  thisPtr->textureCoords[i][1],
340                                  0.0));
341                (*texCoords)[i].set(transVec.x(), transVec.y());
342            }
343        }
344
[5802]345        geometry->setTexCoordArray(0, texCoords.get());
[2225]346    }
347   
348    // Set the parameters for the geometry
349
350    geometry->addPrimitiveSet(new osg::DrawArrays(thisPtr->primitiveType,0,
351                                                  coords->size()));
352    // Get the StateSet for the geoset
[5802]353    osg::ref_ptr<osg::StateSet> stateSet = thisPtr->getStateSet(action);
354    geometry->setStateSet(stateSet.get());
[2225]355   
356    // Add the geoset to a geode
[5802]357    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
358    geode->addDrawable(geometry.get());
[2225]359
[9053]360    // copy name
361    std::string name = stateSet->getName();
362    if (name != "") {
363        geode->setName(name);
364    }
[2225]365    // Add geode to scenegraph
[5802]366    thisPtr->groupStack.top()->addChild(geode.get());
[2225]367
368    return SoCallbackAction::CONTINUE;
369}
[5802]370///////////////////////////////////////////////////////////////
[2225]371SoCallbackAction::Response
[6543]372ConvertFromInventor::preTexture(void* data, SoCallbackAction *,
[2225]373                                const SoNode* node)
374{
375#ifdef DEBUG_IV_PLUGIN
[2896]376    osg::notify(osg::INFO) << "preTexture()  " 
[2225]377              << node->getTypeId().getName().getString() << std::endl;
378#endif
379   
380    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
381   
382    if (thisPtr->soTexStack.size())
[6543]383        thisPtr->soTexStack.pop();
384    thisPtr->soTexStack.push(node);
[2225]385       
386    return SoCallbackAction::CONTINUE;
387}
[6543]388//////////////////////////////////////////////////////////////////////////////////
389SoCallbackAction::Response
[9053]390ConvertFromInventor::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//////////////////////////////////////////////////////////////////////////////////
423SoCallbackAction::Response
[6543]424ConvertFromInventor::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}
[5802]440//////////////////////////////////////////////////////////////////
[2225]441void ConvertFromInventor::transformLight(SoCallbackAction* action,
442                                         const SbVec3f& vec,
443                                         osg::Vec3& transVec)
444{
445    osg::Matrix modelMat;
446    modelMat.set((float *)action->getModelMatrix().getValue());
447
448    transVec.set(vec[0], vec[1], vec[2]);
449    transVec = modelMat.preMult(transVec);
450}
[5802]451///////////////////////////////////////////////////////////////////
[2225]452SoCallbackAction::Response
453ConvertFromInventor::preLight(void* data, SoCallbackAction* action,
454                              const SoNode* node)
455{
456#ifdef DEBUG_IV_PLUGIN
[2896]457    osg::notify(osg::INFO) << "preLight()  " 
[2225]458              << node->getTypeId().getName().getString() << std::endl;
459#endif
460
461    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
462    static int lightNum = 1;
463   
464    // Return if the light is not on
465    const SoLight* ivLight = (const SoLight*) node;
466    if (!ivLight->on.getValue())
467        return SoCallbackAction::CONTINUE;
468
[5802]469    osg::ref_ptr<osg::Light> osgLight = new osg::Light;
[2225]470    osgLight->setLightNum(lightNum++);
[9053]471
472    const char* name = ivLight->getName().getString();
473    osgLight->setName(name);
[2225]474   
475    // Get color and intensity
476    SbVec3f lightColor = ivLight->color.getValue();
477    float intensity = ivLight->intensity.getValue();
478
479    // Set color and intensity
480    osgLight->setDiffuse(osg::Vec4(lightColor[0] * intensity,
481                                   lightColor[1] * intensity,
482                                   lightColor[2] * intensity, 1));
483
484    if (node->isOfType(SoDirectionalLight::getClassTypeId()))
485    {
486        SoDirectionalLight *dirLight = (SoDirectionalLight *) node;
487       
488        osg::Vec3 transVec;
489        thisPtr->transformLight(action, dirLight->direction.getValue(), transVec);
490        osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(),
491                                        transVec.z(), 0));
492    }
493    else if (node->isOfType(SoPointLight::getClassTypeId()))
494    {
495        SoPointLight* ptLight = (SoPointLight *) node;
496
497        osg::Vec3 transVec;
498        thisPtr->transformLight(action, ptLight->location.getValue(), transVec);
499        osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(),
500                                        transVec.z(), 0));
501    }
502    else if (node->isOfType(SoSpotLight::getClassTypeId()))
503    {
504        SoSpotLight* spotLight = (SoSpotLight *) node;
505
506        osgLight->setSpotExponent(spotLight->dropOffRate.getValue() * 128.0);
[2915]507        osgLight->setSpotCutoff(spotLight->cutOffAngle.getValue()*180.0/osg::PI);
[2225]508
509        osg::Vec3 transVec;
510        thisPtr->transformLight(action, spotLight->location.getValue(), transVec);
511        osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(),
512                                        transVec.z(), 0));
513
514        thisPtr->transformLight(action, spotLight->direction.getValue(),transVec);
515        osgLight->setDirection(osg::Vec3(transVec.x(), transVec.y(),
516                                         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();
[5802]524        lightList.push_back(osgLight.get());
[2225]525        thisPtr->lightStack.pop();
526        thisPtr->lightStack.push(lightList);
527    }
528
[9053]529    // add a light source node to the scene graph
530    osg::ref_ptr<osg::LightSource> ls = new osg::LightSource();
531    ls->setLight(osgLight.get());
532    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());
539
[2225]540    return SoCallbackAction::CONTINUE;
541}
[5802]542///////////////////////////////////////////////////////////////////////////////////////
[6543]543osg::ref_ptr<osg::StateSet>
544ConvertFromInventor::getStateSet(SoCallbackAction* action)
[2225]545{
[5802]546    osg::ref_ptr<osg::StateSet> stateSet = new osg::StateSet;
[2225]547   
548    // Inherit modes from the global state
[3480]549    stateSet->clear();
[2225]550
[7348]551    // Convert the IV texture to OSG texture if any
552    osg::ref_ptr<osg::Texture2D> texture;
553    const SoNode *ivTexture = soTexStack.top();
554    if (ivTexture)
555    {
556        osg::notify(osg::INFO)<<"Have texture"<<std::endl;
557
558        // Found a corresponding OSG texture object
559        if (ivToOsgTexMap[ivTexture])
560            texture = ivToOsgTexMap[ivTexture];
561        else
562        {
563            // Create a new osg texture
564            texture = convertIVTexToOSGTex(ivTexture, action);
565
566            // Add the new texture to the database
567            ivToOsgTexMap[ivTexture] = texture.get();
568        }
569       
570        stateSet->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::ON);
[9053]571       
572        // propogate name
[9451]573        if(texture.valid())
574        {
575            std::string name = texture->getName();
576            if (name != "")
577                stateSet->setName(name);
578        }
[7348]579        // Set the texture environment
580        osg::ref_ptr<osg::TexEnv> texEnv = new osg::TexEnv;
581        switch (action->getTextureModel())
582        {
583            case SoTexture2::MODULATE:
584                texEnv->setMode(osg::TexEnv::MODULATE);
585                break;
586            case SoTexture2::DECAL:
587                texEnv->setMode(osg::TexEnv::DECAL);
588                break;
589            case SoTexture2::BLEND:
590                texEnv->setMode(osg::TexEnv::BLEND);
591                break;
[9585]592#if defined(__COIN__) && ((COIN_MAJOR_VERSION==2 && COIN_MINOR_VERSION>=2) || (COIN_MAJOR_VERSION>2))
[7348]593            // SGI's Inventor does not have REPLACE mode, but the Coin 3D library does.
594            // Coin supports REPLACE since 2.2 release, TGS Inventor from 4.0.
595            // Let's convert to the TexEnv anyway.
[9585]596            case SoTexture2::REPLACE:
[7348]597                texEnv->setMode(osg::TexEnv::REPLACE);
598                break;
[9585]599#endif
600            default:
601                break;
602
[7348]603        }
604        stateSet->setTextureAttributeAndModes(0,texEnv.get(),osg::StateAttribute::ON);
605    }
606
[2225]607    SbColor ambient, diffuse, specular, emission;
608    float shininess, transparency;
609
610    // Get the material colors
611    action->getMaterial(ambient, diffuse, specular, emission,
[2485]612                shininess, transparency, 0);
[2225]613   
614    // Set transparency
[7348]615    SbBool hasTextureTransparency = FALSE;
616    if (ivTexture) {
617      SbVec2s tmp;
618      int bpp;
619      if (ivTexture->isOfType(SoTexture2::getClassTypeId()))
620        ((SoTexture2*)ivTexture)->image.getValue(tmp, bpp);
621#ifdef __COIN__
622      else
623      if (ivTexture->isOfType(SoVRMLImageTexture::getClassTypeId())) {
624        const SbImage *img = ((SoVRMLImageTexture*)ivTexture)->getImage();
625        if (img) img->getValue(tmp, bpp);
626        else bpp = 0;
627      }
628#endif
629      hasTextureTransparency = bpp==4 || bpp==2;
630    }
631
632    if (transparency > 0 || hasTextureTransparency)
[2225]633    {
[5802]634        osg::ref_ptr<osg::BlendFunc> transparency = new osg::BlendFunc;
635        stateSet->setAttributeAndModes(transparency.get(),
[2225]636                                       osg::StateAttribute::ON);
637   
638        // Enable depth sorting for transparent objects
639        stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
640    }
641   
642    // Set linewidth
643    if (action->getLineWidth())
644    {
[5802]645        osg::ref_ptr<osg::LineWidth> lineWidth = new osg::LineWidth;
[2225]646        lineWidth->setWidth(action->getLineWidth());
[5802]647        stateSet->setAttributeAndModes(lineWidth.get(), osg::StateAttribute::ON);
[2225]648    }
649
650    // Set pointsize
651    if (action->getPointSize())
652    {
[5802]653        osg::ref_ptr<osg::Point> point = new osg::Point;
[2225]654        point->setSize(action->getPointSize());
[5802]655        stateSet->setAttributeAndModes(point.get(), osg::StateAttribute::ON);
[2225]656    }
657   
658    // Set draw mode
659    switch (action->getDrawStyle())
660    {
661        case SoDrawStyle::FILLED:
[3920]662        {
663#if 0
664// OSG defaults to filled draw style, so no need to set redundent state.
665            osg::PolygonMode *polygonMode = new osg::PolygonMode;
[2225]666            polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK,
667                                 osg::PolygonMode::FILL);
[3920]668            stateSet->setAttributeAndModes(polygonMode, osg::StateAttribute::ON);
669#endif
[2225]670            break;
[3920]671        }
[2225]672        case SoDrawStyle::LINES:
[3920]673        {
[5802]674            osg::ref_ptr<osg::PolygonMode> polygonMode = new osg::PolygonMode;
[2225]675            polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK,
676                                 osg::PolygonMode::LINE);
[5802]677            stateSet->setAttributeAndModes(polygonMode.get(), osg::StateAttribute::ON);
[2225]678            break;
[3920]679        }
[2225]680        case SoDrawStyle::POINTS:
[3920]681        {
[5802]682            osg::ref_ptr<osg::PolygonMode> polygonMode = new osg::PolygonMode;
[2225]683            polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK,
684                                 osg::PolygonMode::POINT);
[5802]685            stateSet->setAttributeAndModes(polygonMode.get(), osg::StateAttribute::ON);
[2225]686            break;
[3920]687        }
[2225]688        case SoDrawStyle::INVISIBLE:
689            // check how to handle this in osg.
690            break;
691    }
692
693    // Set back face culling
694    if (action->getShapeType() == SoShapeHints::SOLID)
695    {
[5802]696        osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace;
[2225]697        cullFace->setMode(osg::CullFace::BACK);
[5802]698        stateSet->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
[2225]699    }
700
701    // Set lighting
702    if (action->getLightModel() == SoLightModel::BASE_COLOR)
703        stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
704    else
705    {
706        // Set the material
[5802]707        osg::ref_ptr<osg::Material> material = new osg::Material;
[2225]708
709        material->setAmbient(osg::Material::FRONT_AND_BACK,
710                             osg::Vec4(ambient[0], ambient[1], ambient[2],
711                                       1.0 - transparency));
712        material->setDiffuse(osg::Material::FRONT_AND_BACK,
713                             osg::Vec4(diffuse[0], diffuse[1], diffuse[2],
714                                       1.0 - transparency));
715        material->setSpecular(osg::Material::FRONT_AND_BACK,
716                              osg::Vec4(specular[0], specular[1], specular[2],
717                                        1.0 - transparency));
718        material->setEmission(osg::Material::FRONT_AND_BACK,
719                              osg::Vec4(emission[0], emission[1], emission[2],
720                                        1.0 - transparency));
721        material->setTransparency(osg::Material::FRONT_AND_BACK, transparency);
722        if (specular[0] || specular[1] || specular[2])
723            material->setShininess(osg::Material::FRONT_AND_BACK,
724                                   shininess*128.0);
725        else
726            material->setShininess(osg::Material::FRONT_AND_BACK, 0.0);
727
728        material->setColorMode(osg::Material::DIFFUSE);
729
[5802]730        stateSet->setAttributeAndModes(material.get(), osg::StateAttribute::ON);
[9053]731        stateSet->setName(appearanceName.getString());
[2225]732        stateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);
733
[3920]734#if 0
735// disable as two sided lighting causes problem under NVidia, and the above osg::Material settings are single sided anway..
[2225]736        // Set two sided lighting
737        osg::LightModel* lightModel = new osg::LightModel;
738        lightModel->setTwoSided(true);
739        stateSet->setAttributeAndModes(lightModel, osg::StateAttribute::ON);
[3920]740#endif
[2225]741        // Set lights
742        LightList lightList = lightStack.top();
743        for (unsigned int i = 0; i < lightList.size(); i++)
744            stateSet->setAttributeAndModes(lightList[i],
745                                           osg::StateAttribute::ON);
746    }
747   
748    return stateSet;
749}
[5802]750////////////////////////////////////////////////////////////////////
[6543]751osg::Texture2D*
752ConvertFromInventor::convertIVTexToOSGTex(const SoNode* soNode,
[2225]753                                          SoCallbackAction* action)
754{
[6543]755    osg::notify(osg::INFO)<<"convertIVTexToOSGTex of type "<<
756        soNode->getTypeId().getName().getString()<<std::endl;
[3920]757
[6543]758    SbVec2s soSize;
759    int soNC;
760
[2225]761    // Get the texture size and components
[6543]762    const unsigned char* soImageData = action->getTextureImage(soSize, soNC);
763    if (!soImageData) {
764        osg::notify(osg::WARN) << "IV import warning: Error while loading texture data." << std::endl;
[2225]765        return NULL;
[6543]766    }
767
[2225]768    // Allocate memory for image data
[6543]769    unsigned char* osgImageData = new unsigned char[soSize[0] * soSize[1] * soNC];
770
[2225]771    // Copy the texture image data from the inventor texture
[6543]772    memcpy(osgImageData, soImageData, soSize[0] * soSize[1] * soNC);
[2225]773
[9053]774    // Copy the name
775    std::string name = soNode->getName().getString();
776
[6543]777    // File name
778    std::string fileName;
779    if (soNode->isOfType(SoTexture2::getClassTypeId()))
780        fileName = ((SoTexture2*)soNode)->filename.getValue().getString();
[7348]781#ifdef __COIN__
[6543]782    else
783    if (soNode->isOfType(SoVRMLImageTexture::getClassTypeId()))
784        fileName = ((SoVRMLImageTexture*)soNode)->url.getNum() >= 1 ?
785                   ((SoVRMLImageTexture*)soNode)->url.getValues(0)[0].getString() : "";
[6544]786#endif
[6543]787    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 << " -> ";
792    if (fileName[0]=='\"') fileName.erase(fileName.begin());
793    if (fileName.size() > 0 && fileName[fileName.size()-1]=='\"')
794        fileName.erase(fileName.begin()+fileName.size()-1);
795    osg::notify(osg::INFO) << fileName << std::endl;
796
797    // Create the osg::Image
798    osg::ref_ptr<osg::Image> osgImage = new osg::Image;
799    osgImage->setFileName(fileName);
[2225]800    GLenum formats[] = {GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA};
[6543]801    osgImage->setImage(soSize[0], soSize[1], 0, soNC, formats[soNC-1],
802                       GL_UNSIGNED_BYTE, osgImageData, osg::Image::USE_NEW_DELETE);
[2225]803
[6543]804    // Create the osg::Texture2D
805    osg::Texture2D *osgTex = new osg::Texture2D;
806    osgTex->setImage(osgImage.get());
[9053]807    if (name != "") {
808        osgTex->setName(name);
809    }
[2225]810
811    static std::map<SoTexture2::Wrap, osg::Texture2D::WrapMode> texWrapMap;
812    static bool firstTime = true;
813    if (firstTime)
814    {
815        texWrapMap[SoTexture2::CLAMP] = osg::Texture2D::CLAMP;
816        texWrapMap[SoTexture2::REPEAT] = osg::Texture2D::REPEAT;
817        firstTime = false;
818    }
819         
820    // Set texture wrap mode
[7348]821#ifdef __COIN__
[6543]822    if (soNode->isOfType(SoVRMLImageTexture::getClassTypeId())) {
823        // It looks like there is a high probability of bug in Coin (investigated on version 2.4.6).
824        // action->getTextureWrap() returns correct value on SoTexture2 (SoTexture2::CLAMP = 0x2900,
825        // and REPEAT = 0x2901), but SoVRMLImageTexture returns incorrect value of
826        // SoGLImage::REPEAT = 0, CLAMP = 1, CLAMP_TO_EDGE = 2).
827        // So, let's not use action and try to get correct value directly from texture node.
828        // PCJohn-2007-04-22
829        osgTex->setWrap(osg::Texture2D::WRAP_S, ((SoVRMLImageTexture*)soNode)->repeatS.getValue() ?
830            osg::Texture2D::REPEAT : osg::Texture2D::CLAMP_TO_EDGE);
831        osgTex->setWrap(osg::Texture2D::WRAP_T, ((SoVRMLImageTexture*)soNode)->repeatT.getValue() ?
832            osg::Texture2D::REPEAT : osg::Texture2D::CLAMP_TO_EDGE);
[6544]833    }
834    else
835#endif
836    {
[6543]837        // Proper way to determine wrap mode
838        osgTex->setWrap(osg::Texture2D::WRAP_S, texWrapMap[action->getTextureWrapS()]);
839        osgTex->setWrap(osg::Texture2D::WRAP_T, texWrapMap[action->getTextureWrapT()]);
840    }
[2225]841
[6543]842    return osgTex;
[2225]843}
[5802]844///////////////////////////////////////////////////////////////////
[2225]845SoCallbackAction::Response
[9053]846ConvertFromInventor::preInfo(void* data, SoCallbackAction* action,
[2225]847                              const SoNode* node)
848{
849#ifdef DEBUG_IV_PLUGIN
[9053]850    osg::notify(osg::INFO) << "preInfo()    " 
851              << node->getTypeId().getName().getString() << std::endl;
852#endif
853    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
854    SoInfo* info = (SoInfo*)node;
855    thisPtr->transformInfoName = info->string.getValue();
856
857    return SoCallbackAction::CONTINUE;
858}
859   
860///////////////////////////////////////////////////////////////////
861SoCallbackAction::Response
862ConvertFromInventor::preGroup(void* data, SoCallbackAction* action,
863                              const SoNode* node)
864{
865#ifdef DEBUG_IV_PLUGIN
[2896]866    osg::notify(osg::INFO) << "preGroup()    " 
[2225]867              << node->getTypeId().getName().getString() << std::endl;
868#endif
[9193]869
[2225]870    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
871
[6543]872    // Create a new Group or LOD and add it to the stack
873    osg::ref_ptr<osg::Group> group;
[9053]874    if (node->isOfType(SoLOD::getClassTypeId())) {
[6543]875        group = new osg::LOD;
[9053]876    }
877    else {
[6543]878        group = new osg::Group;
[9053]879    }
880
[9193]881
[5802]882    thisPtr->groupStack.top()->addChild(group.get());
883    thisPtr->groupStack.push(group.get());
[9053]884   
[9193]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;
[2225]894
[9193]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();
[9053]900
[9193]901            thisPtr->addMatrixTransform(name, axis, angle, center, trans, scale);
902        }
[9053]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
[2225]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}
[5802]943//////////////////////////////////////////////////////////////
[2225]944SoCallbackAction::Response
[6543]945ConvertFromInventor::postGroup(void* data, SoCallbackAction* action,
[2225]946                               const SoNode* node)
947{
[6543]948    // Handle SoLOD nodes specially
949    if (node->isOfType(SoLOD::getClassTypeId()))
950        return postLOD(data, action, node);
951
[2225]952#ifdef DEBUG_IV_PLUGIN
[2896]953    osg::notify(osg::INFO) << "postGroup()   " 
[2225]954              << node->getTypeId().getName().getString() << std::endl;
955#endif
956    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
957
[6543]958    // Pop all the groups that are Transforms
[5802]959    osg::ref_ptr<osg::Group> group = thisPtr->groupStack.top();
[2225]960    while (strcmp(group->className(), "MatrixTransform") == 0)
961    {
962        thisPtr->groupStack.pop();
963        group = thisPtr->groupStack.top();
964    }
965
[6543]966    // Pop the group from the stack
[2225]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}
[5802]978////////////////////////////////////////////////////////////
[2225]979SoCallbackAction::Response
[6543]980ConvertFromInventor::postLOD(void* data, SoCallbackAction *,
981                             const SoNode* node)
[2225]982{
983#ifdef DEBUG_IV_PLUGIN
[6543]984    osg::notify(osg::INFO) << "postLOD()    " 
[2225]985              << node->getTypeId().getName().getString() << std::endl;
986#endif
987
988    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
989
[6543]990    // Inventor and OSG LOD node
[2225]991    SoLOD *ivLOD = (SoLOD *) node;
[6543]992    osg::LOD *lod = dynamic_cast<osg::LOD*>(thisPtr->groupStack.top());
[2225]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
[6543]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
[2225]1010    // Get the ranges and set it
[6543]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    }
[2225]1021
[6543]1022    // Pop the group from the stack
1023    thisPtr->groupStack.pop();
1024
[2225]1025    return SoCallbackAction::CONTINUE;
1026}
[5802]1027/////////////////////////////////////////////////////////////
[2225]1028SoCallbackAction::Response
1029ConvertFromInventor::preRotor(void* data, SoCallbackAction *,
1030                              const SoNode* node)
1031{
1032#ifdef DEBUG_IV_PLUGIN
[2896]1033    osg::notify(osg::INFO) << "preRotor()  " 
[2225]1034              << node->getTypeId().getName().getString() << std::endl;
1035#endif
1036
1037    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
1038
1039    // Get the parameters for the inventor Rotor
1040    SoRotor *ivRotor = (SoRotor *) node;
1041    SbVec3f ivAxis;
1042    float angle;
1043    ivRotor->rotation.getValue(ivAxis, angle);
1044
1045    // Create a new osg::MatrixTransform
[5802]1046    osg::ref_ptr<osg::MatrixTransform> rotorTransform = new osg::MatrixTransform;
[2225]1047   
1048    // Create a Rotor Callback equivalent to the inventor Rotor
1049    osg::Vec3 pivot(0, 0, 0);
1050    osg::Vec3 axis(ivAxis[0], ivAxis[1], ivAxis[2]);
[5802]1051    osg::ref_ptr<osgUtil::TransformCallback> rotorCallback
[2225]1052        = new osgUtil::TransformCallback(pivot, axis,
[2915]1053                                         2 * osg::PI * ivRotor->speed.getValue());
[2225]1054
1055    // Set the app callback
[5802]1056    rotorTransform->setUpdateCallback(rotorCallback.get());
[2225]1057   
1058    // Push the rotor transform onto the group stack
[5802]1059    thisPtr->groupStack.top()->addChild(rotorTransform.get());
[6543]1060    thisPtr->groupStack.push(rotorTransform.get());
[2225]1061
1062    return SoCallbackAction::CONTINUE;
1063}
[5802]1064////////////////////////////////////////////////////////////////
[2225]1065SoCallbackAction::Response
1066ConvertFromInventor::prePendulum(void* data, SoCallbackAction *,
1067                                 const SoNode* node)
1068{
1069#ifdef DEBUG_IV_PLUGIN
[2896]1070    osg::notify(osg::INFO) << "prePendulum()  " 
[2225]1071              << node->getTypeId().getName().getString() << std::endl;
1072#endif
1073
1074    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
1075
1076    // Get the parameters for the inventor Pendulum
1077    SoPendulum *ivPendulum = (SoPendulum *) node;
1078    SbVec3f ivAxis0, ivAxis1;
1079    float startAngle, endAngle;
1080    ivPendulum->rotation0.getValue(ivAxis0, startAngle);
1081    ivPendulum->rotation1.getValue(ivAxis1, endAngle);
1082
1083    // Create a new osg::MatrixTransform
[5802]1084    osg::ref_ptr<osg::MatrixTransform> pendulumTransform = new osg::MatrixTransform;
[2225]1085   
1086    // Create a Pendulum Callback equivalent to the inventor Rotor
1087    osg::Vec3 axis(ivAxis0[0], ivAxis0[1], ivAxis0[2]);
1088    PendulumCallback* pendulumCallback
1089        = new PendulumCallback(axis, startAngle, endAngle,
1090                               ivPendulum->speed.getValue());
1091
1092    // Set the app callback
1093    pendulumTransform->setUpdateCallback(pendulumCallback);
1094   
1095    // Push the pendulum transform onto the group stack
[5802]1096    thisPtr->groupStack.top()->addChild(pendulumTransform.get());
[6543]1097    thisPtr->groupStack.push(pendulumTransform.get());
[2225]1098
1099    return SoCallbackAction::CONTINUE;
1100}
[5802]1101////////////////////////////////////////////////////////////////
[2225]1102SoCallbackAction::Response
1103ConvertFromInventor::preShuttle(void* data, SoCallbackAction *,
1104                                const SoNode* node)
1105{
1106#ifdef DEBUG_IV_PLUGIN
[2896]1107    osg::notify(osg::INFO) << "preShuttle()  " 
[2225]1108              << node->getTypeId().getName().getString() << std::endl;
1109#endif
1110
1111    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
1112
1113    // Get the parameters for the inventor Shuttle
1114    SoShuttle *ivShuttle = (SoShuttle *) node;
1115    SbVec3f ivStartPos, ivEndPos;
1116    ivStartPos = ivShuttle->translation0.getValue();
1117    ivEndPos = ivShuttle->translation1.getValue();
1118
1119    // Create a new osg::MatrixTransform
[5802]1120    osg::ref_ptr<osg::MatrixTransform> shuttleTransform = new osg::MatrixTransform;
[2225]1121   
1122    // Create a shuttle Callback equivalent to the inventor Rotor
1123    osg::Vec3 startPos(ivStartPos[0], ivStartPos[1], ivStartPos[2]);
1124    osg::Vec3 endPos(ivEndPos[0], ivEndPos[1], ivEndPos[2]);
1125    ShuttleCallback* shuttleCallback
1126        = new ShuttleCallback(startPos, endPos, ivShuttle->speed.getValue());
1127
1128    // Set the app callback
1129    shuttleTransform->setUpdateCallback(shuttleCallback);
1130   
1131    // Push the shuttle transform onto the group stack
[5802]1132    thisPtr->groupStack.top()->addChild(shuttleTransform.get());
[6543]1133    thisPtr->groupStack.push(shuttleTransform.get());
[2225]1134
1135    return SoCallbackAction::CONTINUE;
1136}
[5802]1137////////////////////////////////////////////////////////////
[2225]1138void ConvertFromInventor::addVertex(SoCallbackAction* action,
[5802]1139                                    const SoPrimitiveVertex *v,
1140                                    int index)
[2225]1141{
1142    // Get the coordinates of the vertex
1143    SbVec3f pt = v->getPoint();
1144    vertices.push_back(osg::Vec3(pt[0], pt[1], pt[2]));
1145
1146    // Get the normal of the vertex
1147    SbVec3f norm = v->getNormal();
1148
1149    if ((normalBinding == osg::Geometry::BIND_PER_VERTEX) ||
1150        (normalBinding == osg::Geometry::BIND_PER_PRIMITIVE && index == 0))
1151    {
1152        if (vertexOrder == CLOCKWISE)
1153            normals.push_back(osg::Vec3(-norm[0], -norm[1], -norm[2]));
1154        else
1155            normals.push_back(osg::Vec3(norm[0], norm[1], norm[2]));
1156    }
1157
1158    if (colorBinding == osg::Geometry::BIND_PER_VERTEX ||
1159            colorBinding == osg::Geometry::BIND_PER_PRIMITIVE)
1160    {
1161        // Get the material/color
1162        SbColor ambient, diffuse, specular, emission;
1163        float transparency, shininess;
1164        action->getMaterial(ambient, diffuse, specular, emission, shininess,
1165                            transparency, v->getMaterialIndex());
1166        if (colorBinding == osg::Geometry::BIND_PER_VERTEX)
1167            colors.push_back(osg::Vec4(diffuse[0], diffuse[1], diffuse[2],
1168                                       1.0 - transparency));
1169        else if (colorBinding == osg::Geometry::BIND_PER_PRIMITIVE && index == 0)
1170            colors.push_back(osg::Vec4(diffuse[0], diffuse[1], diffuse[2],
1171                                       1.0 - transparency));
1172    }
1173
1174    // Get the texture coordinates
1175    SbVec4f texCoord = v->getTextureCoords();
1176    textureCoords.push_back(osg::Vec2(texCoord[0], texCoord[1]));
1177}
[5802]1178////////////////////////////////////////////////////////////////////////////
[9053]1179void 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////////////////////////////////////////////////////////////////////////////
[2225]1237void ConvertFromInventor::addTriangleCB(void* data, SoCallbackAction* action,
[5802]1238                                        const SoPrimitiveVertex* v0,
[2225]1239                                        const SoPrimitiveVertex* v1,
1240                                        const SoPrimitiveVertex* v2)
1241{
1242    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
1243   
1244    switch (thisPtr->vertexOrder)
1245    {
1246        case CLOCKWISE:
1247            thisPtr->addVertex(action, v0, 0);
1248            thisPtr->addVertex(action, v2, 1);
1249            thisPtr->addVertex(action, v1, 2);
1250            break;
1251        case COUNTER_CLOCKWISE:
1252            thisPtr->addVertex(action, v0, 0);
1253            thisPtr->addVertex(action, v1, 1);
1254            thisPtr->addVertex(action, v2, 2);
1255            break;
1256    }
1257
1258    thisPtr->numPrimitives++;
1259    thisPtr->primitiveType = osg::PrimitiveSet::TRIANGLES;
1260}
[5802]1261////////////////////////////////////////////////////////////////////////////////
[2225]1262void ConvertFromInventor::addLineSegmentCB(void* data, SoCallbackAction* action,
1263                                           const SoPrimitiveVertex* v0,
1264                                           const SoPrimitiveVertex* v1)
1265{
1266    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
1267
1268    thisPtr->addVertex(action, v0, 0);
1269    thisPtr->addVertex(action, v1, 1);
1270
1271    thisPtr->numPrimitives++;
1272    thisPtr->primitiveType = osg::PrimitiveSet::LINES;
1273}
[5802]1274//////////////////////////////////////////////////////////////////////////
[2225]1275void ConvertFromInventor::addPointCB(void* data, SoCallbackAction* action,
1276                                     const SoPrimitiveVertex* v0)
1277{
1278    ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);
1279
1280    thisPtr->addVertex(action, v0, 0);
1281
1282    thisPtr->numPrimitives++;
1283    thisPtr->primitiveType = osg::PrimitiveSet::POINTS;
1284}
Note: See TracBrowser for help on using the browser.