示例#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;
}
OSG_BASE_DLLMAPPING bool MatrixLookAt(OSG::Matrix &result,
                                      OSG::Pnt3f   from, 
                                      OSG::Pnt3f   at, 
                                      OSG::Vec3f   up    )
{
    Vec3f view;
    Vec3f right;
    Vec3f newup;
    Vec3f tmp;

    view = from - at;
    view.normalize();

    right = up.cross(view);

    if(right.dot(right) < TypeTraits<Real>::getDefaultEps())
    {
        return true;
    }

    right.normalize();

    newup = view.cross(right);

    result.setIdentity ();
    result.setTranslate(from[0], from[1], from[2]);

    Matrix tmpm;

    tmpm.setValue(right, newup, view);

    result.mult(tmpm);

    return false;
}
示例#3
0
OSG::NodeTransitPtr createScene(void)
{
    // create the scene:
    OSG::TransformTransitPtr xform = OSG::Transform::create();

    OSG::Matrix mat;
    mat.setTranslate(OSG::Vec3f(2,0,0));
    xform->setMatrix(mat);

    OSG::NodeTransitPtr scene = OSG::Node::create();
    scene->addChild(createLabeledScene());
    scene->setCore(xform);

    OSG::commitChanges();

    return scene;
}
OSG_BASE_DLLMAPPING bool MatrixLookAt(OSG::Matrix &result,
                                      OSG::Real32  fromx,
                                      OSG::Real32  fromy,
                                      OSG::Real32  fromz,
                                      OSG::Real32  atx,
                                      OSG::Real32  aty,
                                      OSG::Real32  atz,
                                      OSG::Real32  upx,
                                      OSG::Real32  upy,
                                      OSG::Real32  upz)
{
    Vec3f view;
    Vec3f right;
    Vec3f newup;
    Vec3f up;

    view.setValues(fromx - atx , fromy - aty, fromz - atz);
    view.normalize();

    up.setValues(upx, upy, upz);

    right = up.cross(view);

    if(right.dot(right) < TypeTraits<Real>::getDefaultEps())
    {
        return true;
    }

    right.normalize();

    newup = view.cross(right);

    result.setIdentity ();
    result.setTranslate(fromx, fromy, fromz);

    Matrix tmpm;

    tmpm.setValue(right, newup, view);

    result.mult(tmpm);

    return false;
}
//
// In  case the clip plane data change this function is called
//
void updateClipPlanes(const VecClipPlaneData& vec)
{
    int sz  = vec.size();

    for(int i = 0; i < iNumClipPlanes; ++i)
    {
        OSG::ClipPlaneChunk *clipPlaneChunk =
            vecClipPlaneDetails[i]._clipPlaneChunk;

        clipPlaneChunk->setEnable(false);

        if(i < sz)
        {
            const ClipPlaneData& data = vec[i];

            //
            // Update the clip plane chunk
            //
            clipPlaneChunk->setEquation(data._equation);
            clipPlaneChunk->setEnable  (data._enabled );

            //
            // and the plane transform core
            //
            OSG::Matrix rotMat;
            OSG::Vec4f v1(0.f, 0.f, -1.f, 0.f);
            OSG::Quaternion q(OSG::Vec3f(v1), OSG::Vec3f(data._equation));
            rotMat.setTransform(q);

            OSG::Matrix mat;
            OSG::Vec3f v2(0.0f, 0.0f, data._equation[3]);
            mat.setTranslate(v2);

            mat.multLeft(rotMat);

            vecClipPlaneDetails[i]._planeTrafoCore->setMatrix(mat);
        }
    }
}
OSG::NodeTransitPtr createScenegraph(void)
{
    // At first we load all needed models from file
    OSG::NodeRecPtr w_high   = 
        OSG::SceneFileHandler::the()->read("Data/woman_high.wrl");

    OSG::NodeRecPtr w_medium = 
        OSG::SceneFileHandler::the()->read("Data/woman_medium.wrl");

    OSG::NodeRecPtr w_low    = 
        OSG::SceneFileHandler::the()->read("Data/woman_low.wrl");
    
    // we check the result
    if((w_high == NULL) || (w_medium == NULL)|| (w_low == NULL))
    {
        std::cout << "It was not possible to load all needed models from file"
                << std::endl;
        return OSG::NodeTransitPtr();
    }
    
    // now the LOD core
    OSG::DistanceLODRecPtr lod = OSG::DistanceLOD::create();
    lod->editSFCenter()->setValue(OSG::Pnt3f(0,0,0));
    lod->editMFRange()->push_back(200);
    lod->editMFRange()->push_back(500);
    
    // the node containing the LOD core. The three models will be
    // added as its children
    OSG::NodeRecPtr lodNode = OSG::Node::create();
    lodNode->setCore(lod);
    lodNode->addChild(w_high);
    lodNode->addChild(w_medium);
    lodNode->addChild(w_low);
    
    // create the node with switch core ********************
    OSG::SwitchRecPtr sw = OSG::Switch::create();
    //Notice: the first choice is 0
    sw->setChoice(0);
    
    OSG::NodeRecPtr switchNode = OSG::Node::create();
    switchNode->setCore(sw);
    switchNode->addChild(lodNode);
    
    //end switch creation **********************************
    
    OSG::NodeRecPtr root = OSG::Node::create();
    root->setCore(OSG::Group::create());
    root->addChild(switchNode);
    
    // we know want to extract the mesh geometry out of the graph
    // it is sufficent to pass the model only as root for searching
    OSG::NodeRecPtr     womanGeometry = checkName(w_high);
    OSG::GeometryRecPtr geo = 
        dynamic_cast<OSG::Geometry *>(womanGeometry->getCore());
    
    //new node with "old" geometry core referenced
    OSG::NodeRecPtr woman = OSG::Node::create();
    woman->setCore(geo);
    
    //translate it a bit to see both women
    OSG::NodeRecPtr      womanTrans = OSG::Node     ::create();
    OSG::TransformRecPtr t          = OSG::Transform::create();
    OSG::Matrix m;
    m.setIdentity();
    m.setTranslate(OSG::Vec3f(0,0,200));
    t->setMatrix(m);
        
    womanTrans->setCore(t);
    womanTrans->addChild(woman);
    
    //add it to the root
    root->addChild(womanTrans);
    
    return OSG::NodeTransitPtr(root);
}
void updateScene(const std::string &filename, OSG::Image::PixelFormat compressTo = OSG::Image::OSG_INVALID_PF)
{
    // Try to create the new image
    OSG::ImageRecPtr imagePtr = 
        OSG::ImageFileHandler::the()->read(filename.c_str());

    if (imagePtr == NULL)
        return;

    if(compressTo != OSG::Image::OSG_INVALID_PF)
    {
        imagePtr->reformat(compressTo);
    }

    // Update information on the screen
    OSG::StatStringElem *statElem = 
        statfg->editCollector()->getElem(textureFormatDesc);

    switch (imagePtr->getPixelFormat())
    {
        case OSG::Image::OSG_A_PF:
            statElem->set("OSG_A_PF");
            break;
        case OSG::Image::OSG_I_PF:
            statElem->set("OSG_I_PF");
            break;
        case OSG::Image::OSG_L_PF:
            statElem->set("OSG_L_PF");
            break;
        case OSG::Image::OSG_LA_PF:
            statElem->set("OSG_LA_PF");
            break;
        case OSG::Image::OSG_RGB_PF:
            statElem->set("OSG_RGB_PF");
            break;
        case OSG::Image::OSG_RGBA_PF:
            statElem->set("OSG_RGBA_PF");
            break;
        case OSG::Image::OSG_BGR_PF:
            statElem->set("OSG_BGRA_PF");
            break;
        case OSG::Image::OSG_BGRA_PF:
            statElem->set("OSG_BGRA_PF");
            break;
        case OSG::Image::OSG_RGB_DXT1:
            statElem->set("OSG_RGB_DXT1");
            break;
        case OSG::Image::OSG_RGBA_DXT1:
            statElem->set("OSG_RGBA_DXT1");
            break;
        case OSG::Image::OSG_RGBA_DXT3:
            statElem->set("OSG_RGBA_DXT3");
            break;
        case OSG::Image::OSG_RGBA_DXT5:
            statElem->set("OSG_RGBA_DXT5");
            break;
        default:
            statElem->set("???");
            break;
    }
    statElem = statfg->editCollector()->getElem(textureDataTypeDesc);
    switch (imagePtr->getDataType())
    {
        case OSG::Image::OSG_UINT8_IMAGEDATA:
            statElem->set("OSG_UINT8_IMAGEDATA");
            break;
        case OSG::Image::OSG_UINT16_IMAGEDATA:
            statElem->set("OSG_UINT16_IMAGEDATA");
            break;
        case OSG::Image::OSG_UINT32_IMAGEDATA:
            statElem->set("OSG_UINT32_IMAGEDATA");
            break;
        case OSG::Image::OSG_FLOAT16_IMAGEDATA:
            statElem->set("OSG_FLOAT16_IMAGEDATA");
            break;
        case OSG::Image::OSG_FLOAT32_IMAGEDATA:
            statElem->set("OSG_FLOAT32_IMAGEDATA");
            break;
        case OSG::Image::OSG_INT16_IMAGEDATA:
            statElem->set("OSG_INT16_IMAGEDATA");
            break;
        case OSG::Image::OSG_INT32_IMAGEDATA:
            statElem->set("OSG_INT32_IMAGEDATA");
            break;
        default:
            statElem->set("???");
            break;
    }
    ostringstream os;
    os << imagePtr->getWidth() << 'x' << imagePtr->getHeight() << 'x' << imagePtr->getDepth();
    statfg->editCollector()->getElem(textureSizeDesc)->set(os.str());
    statfg->editCollector()->getElem(textureDimensionDesc)->set(imagePtr->getDimension());
    statfg->editCollector()->getElem(textureBPPDesc)->set(imagePtr->getBpp());
    statfg->editCollector()->getElem(textureMipMapCountDesc)->set(imagePtr->getMipMapCount());
    statfg->editCollector()->getElem(textureFrameCountDesc)->set(imagePtr->getFrameCount());

    // Put it all together into a Geometry NodeCore.
    OSG::GeometryRecPtr geo = OSG::makePlaneGeo(imagePtr->getWidth(), imagePtr->getHeight(), 1, 1);
    OSG::NodeRecPtr imageNode = OSG::Node::create();
    imageNode->setCore(geo);
    OSG::NodeRecPtr transNodePtr = OSG::Node::create();
    OSG::TransformRecPtr transPtr = OSG::Transform::create();
    OSG::Matrix transMatrix;
    transMatrix.setTranslate(0.f, 0.f, -1.f);
    transPtr->setMatrix(transMatrix);
    transNodePtr->setCore(transPtr);
    transNodePtr->addChild(imageNode);

    OSG::TextureObjChunkRecPtr texObjChunk = OSG::TextureObjChunk::create();
    texObjChunk->setImage(imagePtr);
    texObjChunk->setWrapS(GL_CLAMP);
    texObjChunk->setWrapT(GL_CLAMP);
    texObjChunk->setMagFilter(GL_NEAREST);
    texObjChunk->setMinFilter(GL_NEAREST);
    OSG::TextureEnvChunkRecPtr texEnvChunk = OSG::TextureEnvChunk::create();
    texEnvChunk->setEnvMode(GL_MODULATE);

    OSG::MaterialChunkRecPtr matChunk = OSG::MaterialChunk::create();
    matChunk->setAmbient(OSG::Color4f(1.f, 1.f, 1.f, 1.f));
    matChunk->setDiffuse(OSG::Color4f(1.f, 1.f, 1.f, 1.f));
    matChunk->setEmission(OSG::Color4f(0.f, 0.f, 0.f, 1.f));
    matChunk->setSpecular(OSG::Color4f(0.f, 0.f, 0.f, 1.f));
    matChunk->setShininess(0);

    OSG::ChunkMaterialRecPtr m = OSG::ChunkMaterial::create();
    m->addChunk(texObjChunk);
    m->addChunk(texEnvChunk);
    m->addChunk(matChunk);

    geo->setMaterial(m);

    scene->clearChildren();
    scene->addChild(transNodePtr);

    if(compressTo != OSG::Image::OSG_INVALID_PF)
    {
        OSG::SceneFileHandler::the()->write(scene->getChild(0), 
                                            "/tmp/comp.osb");
        OSG::SceneFileHandler::the()->write(scene->getChild(0), 
                                            "/tmp/comp.osg");
    }

}
//
// 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();
}
int main(int argc, char *argv[])
{
    // Init the OpenSG subsystem
    OSG::osgInit(argc, argv);

    {
        // We create a GLUT Window (that is almost the same for most applications)
        int winid = setupGLUT(&argc, argv);
        OSG::GLUTWindowRecPtr gwin = OSG::GLUTWindow::create();
        gwin->setGlutId(winid);
        gwin->init();
    
        // Create the face
        std::string family = "SANS";
        OSG::TextFace::Style style = OSG::TextFace::STYLE_PLAIN;
        OSG::UInt32 size = 32;
        OSG::TextPixmapFaceRefPtr face = 
            OSG::TextPixmapFace::create(family, style, size);
        if (face == 0)
        {
            std::cerr << "ERROR: Cannot create face object!" << std::endl;
            return -1;
        }
    
        // Lay out one single line of text
        std::string text = "Hello World!"; // Use UTF-8 encoding!
        OSG::TextLayoutParam layoutParam;
        layoutParam.horizontal = true;
        layoutParam.leftToRight = true;
        layoutParam.topToBottom = true;
        layoutParam.majorAlignment = OSG::TextLayoutParam::ALIGN_FIRST;
        layoutParam.minorAlignment = OSG::TextLayoutParam::ALIGN_FIRST;
        layoutParam.spacing = 1.f;
        layoutParam.length.push_back(0.f);
        layoutParam.maxExtend = 0.f;
        OSG::TextLayoutResult layoutResult;
        face->layout(text, layoutParam, layoutResult);
    
        // Render the text into an OpenSG image
        OSG::Vec2f offset;
        OSG::UInt32 border = 1;
        OSG::ImageRecPtr imagePtr = face->makeImage(layoutResult, offset, border);
        
        // Create the geometry which we will assign the texture to
        OSG::Real32 width = imagePtr->getWidth();
        OSG::Real32 height = imagePtr->getHeight();
        OSG::NodeRecPtr plane = OSG::makePlane(width, height, 1, 1);
    
        // Create the texture that will hold the image
        OSG::SimpleTexturedMaterialRecPtr tex = 
            OSG::SimpleTexturedMaterial::create();
        tex->setImage(imagePtr);
        tex->setEnvMode(GL_MODULATE);
        tex->setDiffuse(OSG::Color3f(1, 0, 0));
    
        // Assign the texture to the geometry
        OSG::GeometryRecPtr geo =
            dynamic_cast<OSG::Geometry *>(plane->getCore());
        geo->setMaterial(tex);
    
        // Transform the geometry so that the origin of the text is at
        // the origin of the world coordinate system
        OSG::NodeRecPtr scene = OSG::Node::create();
        OSG::TransformRecPtr transformPtr = OSG::Transform::create();
        OSG::Matrix m;
        m.setTranslate(offset.x() + width / 2, offset.y() - height / 2, 0);
        transformPtr->setMatrix(m);
        
        scene->setCore(transformPtr);
        scene->addChild(plane);
        
        // Create and setup the SSM
        mgr = new OSG::SimpleSceneManager;
        mgr->setWindow(gwin);
        mgr->setRoot(scene);
    
        // Create a blue background
        OSG::SolidBackgroundRecPtr bg = OSG::SolidBackground::create();
        bg->setColor(OSG::Color3f(0.1, 0.1, 0.5));
        
        gwin->getPort(0)->setBackground(bg);
        
        mgr->showAll();
        
        OSG::commitChanges();
    }

    // Give Control to the GLUT Main Loop
    glutMainLoop();

    return 0;
}