Exemple #1
2
OSG::NodeTransitPtr createLabeledTorus(OSG::Vec3f trans, int idx)
{
    OSG::NodeTransitPtr  node  = OSG::Node::create();
    OSG::TransformRefPtr xform = OSG::Transform::create();
    OSG::Matrix          mat;

    // --- setup transform ------------------
    mat.setIdentity();
    mat.setTranslate(trans);
    xform->setMatrix(mat);
    node->setCore(xform);


    // --- setup label ----------------------
    OSG::NodeRefPtr  labelNode = OSG::Node::create();
    OSG::LabelRefPtr label     = 
        (idx) ? createTextLabel(idx) : createIconLabel();

    updateLabelParams(label, idx);
    labelNode->setCore(label);

    // --- add torus ------------------------
    labelNode->addChild(OSG::makeTorus(.5, 2, 16, 16));

    node->addChild(labelNode);
    return node;
}
// redraw the window
void display( void )
{
    // create the matrix
    OSG::Matrix m;
    OSG::Real32 t = glutGet(GLUT_ELAPSED_TIME);
    
    // set the transforms' matrices
    m.setTransform(OSG::Vec3f(0,
                              0, 
                              OSG::osgSin(t / 1000.f) * 1.5),
                   OSG::Quaternion(OSG::Vec3f (1, 0, 0), 
                                   t / 500.f));

    cyltrans->setMatrix(m);
    
    m.setTransform(OSG::Vec3f(OSG::osgSin(t / 2000.f), 
                              0, 
                              0),
                   OSG::Quaternion(OSG::Vec3f (0, 0, 1), 
                                   t / 2000.f));

    tortrans->setMatrix(m);
    
    mgr->redraw();
}
// redraw the window
void display( void )
{
    // create the matrix
    OSG::Matrix m;
    OSG::Real32 t = glutGet(GLUT_ELAPSED_TIME );
    
    m.setTransform(OSG::Quaternion(OSG::Vec3f(0,1,0), t / 1000.f));
    
    // set the transform's matrix
    trans->setMatrix(m);

    OSG::commitChanges();
   
    mgr->redraw();
}
//
// redraw the window
//
void display(void)
{
    // light spot direction and light position must be provided in eye space
    update_light_state(ubo_light_state, lights);

    // create the matrix
    OSG::Matrix m;
    OSG::Real32 t = glutGet(GLUT_ELAPSED_TIME );
    
    // set the transforms' matrices
    m.setTransform(OSG::Vec3f(0, 0, OSG::osgSin(t / 1000.f) * 1.5),
                   OSG::Quaternion( OSG::Vec3f (1, 0, 0), t / 500.f));

    cyltrans->setMatrix(m);
    
    m.setTransform(OSG::Vec3f(OSG::osgSin(t / 1000.f), 0, 0),
                   OSG::Quaternion( OSG::Vec3f (0, 0, 1), t / 1000.f));

    tortrans->setMatrix(m);

    OSG::commitChanges();
    
    mgr->redraw();
}
// redraw the window
void display( void )
{
    // update the geometry
    OSG::Matrix m;

    OSG::Real32 t = glutGet(GLUT_ELAPSED_TIME );

    m.setTransform(OSG::Vec3f(OSG::osgSin(t / 1000.f),
                              OSG::osgCos(t / 1000.f),
                              OSG::osgSin(t / 1000.f)),

                   OSG::Quaternion( OSG::Vec3f(0,1,0), t / 1000.f));

    trans->setMatrix(m);

    // update the image

    grabImage(image);

    // redraw the screen

    mgr->redraw();
}
/* The main drawing function. */
void DrawGLScene(void)
{
    glMatrixMode(GL_MODELVIEW);
    
    // clear all the buffers - gives OpenGL full control
    // OpenSG doesn't clear the background because of the PassiveBackground object
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    // set the model transformation
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    // set camera position from mouse movement
    glTranslatef(0.0f, 0.0f, -m_distance);
    glRotatef(m_tiltAngle, 1.0f, 0.0f, 0.0f);
    glRotatef(m_twistAngle, 0.0f, 0.0f, 1.0f);
    //glTranslatef(0.0f, 0.0f, -90.0f);
    
    glPushMatrix(); // OpenSG will overwrite
    
    OSG::Real32 proj_matrix[16], model_matrix[16];
    glGetFloatv(GL_PROJECTION_MATRIX, proj_matrix);
    glGetFloatv(GL_MODELVIEW_MATRIX, model_matrix);
    
    // retrieve OpenGL's matrices
    OSG::Matrix proj, model;
    proj.setValue(proj_matrix);
    model.setValue(model_matrix);
    
    newcam->setProjectionMatrix(proj);
    
    // transform the world just like the OpenGL content
    // necessary since OpenSG's modelview transforms start from the unity matrix. 
    newcam->setModelviewMatrix(model);
    
    // setup an initial transformation
    OSG::Matrix m1;
    OSG::Quaternion q1;
  
    // mind that the VRML base coordinate system has different meanings for X, Y, Z, hence the rotation for 90 degrees.
    // this, together with the MatrixCamera code above hooks OpenSG to OpenGL ! 
    m1.setIdentity();
    q1.setValueAsAxisDeg(1, 0, 0., 90); // rotation 
    m1.setRotate(q1);
    trans->setMatrix(m1);

    OSG::commitChanges();
    
    // redraw the OpenSG window content - the calls are a bit after one's own taste 
    pwin->render(mgr->getRenderAction());
    //pwin->frameInit();
    //pwin->frameExit();
    //mgr->redraw();
    
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
    //################ START FOR OPENGL STUFF
    
    // light attributes
    const GLfloat light_ambient[]  = { 0.3f, 0.3f, 0.3f, 1.0f };
    const GLfloat light_diffuse[]  = { 0.52f, 0.5f, 0.5f, 1.0f };
    const GLfloat light_specular[] = { 0.1f, 0.1f, 0.1f, 1.0f };
    
    // setup the light attributes
    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
    
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);
    
    // set the light position
    GLfloat lightPosition[] = { 0.0f, -10.0f, 10.0f, 0.0f };
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
    
    glEnable(GL_NORMALIZE);
    
    glDisable(GL_NORMALIZE);
    //glDisable(GL_BLEND);
    
    glEnable(GL_LIGHTING);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture[0]);   // choose the texture to use.
    
    GLfloat TableDiffuse[] = { 0.3f, 0.0f, 1.0f, 0.5f };
    GLfloat TableSpecular[] = { 0.6f, 0.0f, 0.8f, 0.5f };
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, TableDiffuse);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, TableSpecular);
    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.4f);
    glEnable(GL_BLEND);
    
    gluPartialDisk(quadric,0,12.0f,32,16, 0, 360);    // A Disk Like The One Before  
#if 1 
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_LIGHTING);
    
    // X axis on table    
    glColor3f(1,0,0);
    glBegin(GL_LINES);
    glVertex3f(0,0,0.1f);
    glVertex3f(120,0,0.1f);
    glEnd();
    
    // Y axis on table 
    glColor3f(0,1,0);
    glBegin(GL_LINES);
    glVertex3f(0,0,0.1f);
    glVertex3f(0,120,0.1f);
    glEnd();
    
    glEnable(GL_LIGHTING);
#endif

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);
    
    glDisable(GL_LIGHTING);
    
    // render the cursor
    renderCursor();
    
    // swap the front- and back-buffer
    glutSwapBuffers();
}
//
// react to keys
//
void keyboard(unsigned char k, int, int)
{
    static OSG::Real32 val0 = 0.f;
    static OSG::Real32 val1 = 0.f;

    static OSG::Real32 x1 = 0.f;
    static OSG::Real32 y1 = 0.f;
    static OSG::Real32 z1 = 0.f;

    static OSG::Real32 x2 = 0.f;
    static OSG::Real32 y2 = 0.f;
    static OSG::Real32 z2 = 0.f;

    switch(k)
    {
    case ' ':
        {
            OSG::SceneGraphPrinter sgp(mgr->getRoot());
            sgp.printDownTree(std::cout);
        }
        break;

    case '1':   // enable/disable clip plane 0
        {
            vecClipPlaneData[0]._enabled = !vecClipPlaneData[0]._enabled;
            updateClipPlanes(vecClipPlaneData);
        }
        break;
    case '2':   // enable/disable clip plane 1
        {
            vecClipPlaneData[1]._enabled = !vecClipPlaneData[1]._enabled;
            updateClipPlanes(vecClipPlaneData);
        }
        break;
    case '3':   // enable/disable box geometry
        {
            if(vecGeometries[0] == NULL)
            {
                OSG::Matrix matrix;
                OSG::Vec3f v(10.f,  0.f, 15.f);
                matrix.setTranslate(v);

                OSG::GeometryRefPtr boxGeo  =
                    OSG::makeBoxGeo(15, 15, 15, 1, 1, 1);

                OSG::NodeRefPtr     boxTree = buildGeoTree(scene,
                                                           boxGeo,
                                                           matrix);

                vecGeometries[0] = boxTree;
                scene->addChild(boxTree);
            }
            else
            {
                scene->subChild(vecGeometries[0]);
                vecGeometries[0] = NULL;
            }

//             mgr->showAll();
//             mgr->redraw();
        }
        break;
    case '4':   // enable/disable torus geometry
        {
            if (vecGeometries[1] == NULL)
            {
                OSG::Matrix matrix;
                OSG::Vec3f v( 0.f, 10.f, 0.f);
                matrix.setTranslate(v);

                OSG::GeometryRefPtr torusGeo  = OSG::makeTorusGeo(2, 6, 8, 16);
                OSG::NodeRefPtr     torusTree = buildGeoTree(scene,
                                                             torusGeo, matrix);

                vecGeometries[1] = torusTree;
                scene->addChild(torusTree);
            }
            else
            {
                scene->subChild(vecGeometries[1]);
                vecGeometries[1] = NULL;
            }

//             mgr->showAll();
//             mgr->redraw();
        }
        break;

    case '5':
        {
            OSG::SceneFileHandler::the()->write(mgr->getRoot(), 
                                                "clipplane_model.osb", true);
        }
        break;
    case 'n':   // move clip plane 0 opposite to the normal direction of the plane
        {
            val0 -= 0.2;
            vecClipPlaneData[0]._equation[3] = val0;
            updateClipPlanes(vecClipPlaneData);
        }
        break;
    case 'm':   // move clip plane 0 in the normal direction of the plane
        {
            val0 += 0.2;
            vecClipPlaneData[0]._equation[3] = val0;
            updateClipPlanes(vecClipPlaneData);
        }
        break;
    case ',':   // move clip plane 1 opposite to the normal direction of the plane
        {
            val1 -= 0.2;
            vecClipPlaneData[1]._equation[3] = val1;
            updateClipPlanes(vecClipPlaneData);
        }
        break;
    case '.':   // move clip plane 1 in the normal direction of the plane
        {
            val1 += 0.2;
            vecClipPlaneData[1]._equation[3] = val1;
            updateClipPlanes(vecClipPlaneData);
        }
        break;
    case 'q':   // move box in -x direction
        {
            x1 -= 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v(10.f + x1,  0.f + y1, 15.f + z1);
            matrix.setTranslate(v);

            if(vecGeometries[0] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[0]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 'w':   // move box in +x direction
        {
            x1 += 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v(10.f + x1,  0.f + y1, 15.f + z1);
            matrix.setTranslate(v);

            if(vecGeometries[0] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[0]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 'a':   // move box in -y direction
        {
            y1 -= 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v(10.f + x1,  0.f + y1, 15.f + z1);
            matrix.setTranslate(v);

            if(vecGeometries[0] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[0]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 's':   // move box in +y direction
        {
            y1 += 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v(10.f + x1,  0.f + y1, 15.f + z1);
            matrix.setTranslate(v);

            if(vecGeometries[0] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[0]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 'y':   // move box in -z direction
        {
            z1 -= 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v(10.f + x1,  0.f + y1, 15.f + z1);
            matrix.setTranslate(v);

            if(vecGeometries[0] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[0]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 'x':   // move box in +z direction
        {
            z1 += 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v(10.f + x1,  0.f + y1, 15.f + z1);
            matrix.setTranslate(v);

            if(vecGeometries[0] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[0]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 'e':   // move torus in -x direction
        {
            x2 -= 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v( 0.f + x2, 10.f + y2, 0.f + z2);
            matrix.setTranslate(v);

            if(vecGeometries[1] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[1]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 'r':   // move torus in +x direction
        {
            x2 += 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v( 0.f + x2, 10.f + y2, 0.f + z2);
            matrix.setTranslate(v);

            if(vecGeometries[1] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[1]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 'd':   // move torus in -y direction
        {
            y2 -= 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v( 0.f + x2, 10.f + y2, 0.f + z2);
            matrix.setTranslate(v);

            if(vecGeometries[1] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[1]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 'f':   // move torus in +y direction
        {
            y2 += 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v( 0.f + x2, 10.f + y2, 0.f + z2);
            matrix.setTranslate(v);

            if(vecGeometries[1] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[1]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 'c':   // move torus in -z direction
        {
            z2 -= 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v( 0.f + x2, 10.f + y2, 0.f + z2);
            matrix.setTranslate(v);

            if(vecGeometries[1] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[1]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 'v':   // move torus in +z direction
        {
            z2 += 0.2f;

            OSG::Matrix matrix;
            OSG::Vec3f v( 0.f + x2, 10.f + y2, 0.f + z2);
            matrix.setTranslate(v);

            if(vecGeometries[1] != NULL)
            {
                OSG::TransformRefPtr transformCore =
                    dynamic_cast<OSG::Transform *>(vecGeometries[1]->getCore());

                transformCore->setMatrix(matrix);
            }
        }
        break;
    case 27:
        {
            cleanup();

            OSG::osgExit();
            exit(0);
        }
        break;
    }

    glutPostRedisplay();
}
//
// build geometry scenegraph Tree
//
//
// We need 3 material groups for the clip plane capping trick:
//
//                        scene
//                          |
//     +--------------------+--------------------+
//     |                    |                    |
//  group1 (mat1)        group2 (mat2)        group3 (mat3)
//     |                    |                    |
// geometry (geo1)      geometry (geo2)      geometry (geo1)
//
//    geo1 : actual geometry to draw
//    geo2 : plane geometry coincident with the clip plane
//
//    mat1 : has a stencil chunk that clears the stencil buffer first, than
//           does the inversion, and has a clip plane chunk that enables one
//           clip plane. Sort key 2*i + 0 with i idx of a clip plane.
//    mat2 : has a stencil chunk and settings for drawing the clip plane
//           geometry. All clip planes but the one coincident with the plane
//           are activated. Sort key 2*i + 0 with i idx of a clip plane.
//    mat3 : the material used for the actual geometry. All clip planes are
//           activated. Sort key none.
//
//    For each active clip plane copies of the left two branches need to be
//    added.
//
OSG::NodeTransitPtr buildGeoTree(      OSG::Node     *scene,
                                       OSG::Geometry *geo1,
                                 const OSG::Matrix   &matrix)
{
    //
    // Parent nodes for the left two branches
    //
    VecNodesT vecMaterialNodes1;
    VecNodesT vecMaterialNodes2;

    for(int i = 0; i < iNumClipPlanes; ++i) // foreach clip plane
    {
        //
        // Branch 1: Imprint the geometry clip plane intersection into the
        //           stencil buffer.
        //
        OSG::NodeRefPtr geomNode = OSG::Node::create();
        geomNode->setCore(geo1);

        OSG::NodeRefPtr materialNode1 = OSG::Node::create();
        //
        // Create stencil material core
        //
        OSG::StencilChunkRefPtr stencilChunk1 = OSG::StencilChunk::create();
        stencilChunk1->setClearBuffer(1);
        stencilChunk1->setStencilFunc(GL_NEVER);
        stencilChunk1->setStencilValue(1);
        stencilChunk1->setStencilMask(1);
        stencilChunk1->setStencilOpFail(GL_INVERT);
        stencilChunk1->setStencilOpZFail(GL_INVERT);
        stencilChunk1->setStencilOpZPass(GL_INVERT);

        OSG::ChunkMaterialRefPtr mat1 = OSG::ChunkMaterial::create();
        mat1->addChunk(stencilChunk1);
        mat1->addChunk(vecClipPlaneDetails[i]._clipPlaneChunk);
        mat1->setSortKey(2 * i + 0);

        OSG::MaterialGroupRefPtr mgrp1 = OSG::MaterialGroup::create();
        mgrp1->setMaterial(mat1);

        materialNode1->setCore(mgrp1);
        materialNode1->addChild(geomNode);  // the primary geometry

        vecMaterialNodes1.push_back(materialNode1);

        //
        // Branch 2: Draw plane at places were the stencil buffer is set
        //
        OSG::NodeRefPtr         materialNode2 = OSG::Node        ::create();
        OSG::StencilChunkRefPtr stencilChunk2 = OSG::StencilChunk::create();

        stencilChunk2->setStencilFunc(GL_EQUAL);
        stencilChunk2->setStencilValue(1);
        stencilChunk2->setStencilMask(1);
        stencilChunk2->setStencilOpFail(GL_KEEP);
        stencilChunk2->setStencilOpZFail(GL_ZERO);
        stencilChunk2->setStencilOpZPass(GL_ZERO);

        OSG::SimpleMaterialRefPtr mat2 = OSG::SimpleMaterial::create();
        mat2->setDiffuse(vecClipPlaneDetails[i]._planeColor);
        mat2->setSpecular(OSG::Color3f(1,1,1));
        mat2->setLit(true);

        //
        // Do clip the plane with all clip planes but the one coincident
        // with the plane.
        //
        for(int j = 0; j < iNumClipPlanes; ++j)
        {
            if(i != j)
            {
                mat2->addChunk(vecClipPlaneDetails[j]._clipPlaneChunk);
            }
        }
        mat2->addChunk(stencilChunk2);
        mat2->setSortKey(2 * i + 1);

        OSG::NodeRefPtr planeGeoNode = OSG::Node::create();
        planeGeoNode->setCore(vecClipPlaneDetails[i]._planeGeometryCore);

        OSG::NodeRefPtr planeTrafoNode = OSG::Node::create();
        planeTrafoNode->setCore(vecClipPlaneDetails[i]._planeTrafoCore);
        planeTrafoNode->addChild(planeGeoNode);

        //
        // Neutralize the summed up transformation at this point in the
        // scenegraph since we are describing the plane in the same frame
        // as the clip planes, i.e. world coordinates.
        //
        OSG::NodeRefPtr planeRootNode = OSG::Node::create();
        planeRootNode->setCore(OSG::InverseTransform::create());
        planeRootNode->addChild(planeTrafoNode);

        OSG::MaterialGroupRefPtr mgrp2 = OSG::MaterialGroup::create();
        mgrp2->setMaterial(mat2);

        materialNode2->setCore(mgrp2);
        materialNode2->addChild(planeRootNode); // plane geometry

        vecMaterialNodes2.push_back(materialNode2);
    }

    //
    // Finally, set up a branch for drawing the primary geometry
    //
    OSG::NodeRefPtr           materialNode3 = OSG::Node          ::create();
    OSG::SimpleMaterialRefPtr mat3          = OSG::SimpleMaterial::create();

    mat3->setDiffuse(OSG::Color3f(1,0,0));
    mat3->setSpecular(OSG::Color3f(1,1,1));
    mat3->setLit(true);

    //
    // Clip the geometry with each clip plane
    //
    for(int i = 0; i < iNumClipPlanes; ++i)\
    {
        mat3->addChunk(vecClipPlaneDetails[i]._clipPlaneChunk);
    }

    OSG::MaterialGroupRefPtr mgrp3 = OSG::MaterialGroup::create();
    mgrp3->setMaterial(mat3);

    OSG::NodeRefPtr geometryNode = OSG::Node::create();
    geometryNode->setCore(geo1);

    materialNode3->setCore (mgrp3);
    materialNode3->addChild(geometryNode);

    //
    // The grouping stage core does suppress a reordering
    // of the render states. This is necessary because the
    // stencil states must be rendered in correct order.
    // There is no state sorting across stages, so that
    // would ensure that everything below a stage is rendered
    // together and the sort key can enforce the right order
    // among those things.
    //
    OSG::NodeRefPtr stageNode = OSG::Node::create();
    stageNode->setCore(OSG::GroupingStage::create());

    OSG::NodeRefPtr clipPlanePartNode = OSG::Node::create();
    clipPlanePartNode->setCore(OSG::Group::create());
    stageNode->addChild(clipPlanePartNode);

    for(int i = 0; i < iNumClipPlanes; ++i)
    {
        clipPlanePartNode->addChild(vecMaterialNodes1[i]);
        clipPlanePartNode->addChild(vecMaterialNodes2[i]);
    }

    //
    // The multi switch core is not actually used in this
    // example. However it could be used to define multiple
    // render branches and selectively activate and deactivate
    // them in a given context.
    //
    OSG::MultiSwitchRefPtr selectCore = OSG::MultiSwitch::create();
    selectCore->setSwitchMode(OSG::MultiSwitch::ALL);

    //
    // Add the branches to some parent node.
    //
    OSG::NodeRefPtr selectNode = OSG::Node::create();
    selectNode->setCore(selectCore);

    selectNode->addChild(stageNode);
    selectNode->addChild(materialNode3);

    //
    // Finally, the geometry should be transformable
    //
    OSG::TransformRefPtr transfCore;
    OSG::NodeRefPtr      transfNode =
    OSG::makeCoredNode<OSG::Transform>(&transfCore);

    transfCore->setMatrix(matrix);
    transfNode->addChild(selectNode); // if using sort keys use this
                                       // instead of the former line.

    return OSG::NodeTransitPtr(transfNode);
}