int init(int argc, char **argv)
{
    OSG::osgInit(argc,argv);
    
    // GLUT init

    glutInit(&argc, argv);
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
    int winid = glutCreateWindow("OpenSG");
    glutKeyboardFunc(key);
    glutVisibilityFunc(vis);
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);       
    glutMouseFunc(mouse);   
    glutMotionFunc(motion); 
    
    glutIdleFunc(display);  

    // glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
    
//    glEnable( GL_DEPTH_TEST );
//    glEnable( GL_LIGHTING );
//    glEnable( GL_LIGHT0 );
//    glFrontFace(GL_CW);
    glEnable(GL_CULL_FACE);

    // OSG

    OSG::SceneFileHandler::the()->print();

    // create the graph

    // beacon for camera and light  
    OSG::NodeUnrecPtr b1n = OSG::Node::create();
    OSG::GroupUnrecPtr b1 = OSG::Group::create();

    b1n->setCore( b1 );

    // transformation
    OSG::NodeUnrecPtr t1n = OSG::Node::create();
    OSG::TransformUnrecPtr t1 = OSG::Transform::create();

    t1n->setCore( t1 );
    t1n->addChild( b1n );

    cam_trans = t1;

    // light
    
    OSG::NodeUnrecPtr dlight = OSG::Node::create();
    OSG::DirectionalLightUnrecPtr dl = OSG::DirectionalLight::create();

    dlight->setCore( dl );
//    dlight->setCore( Group::create() );
    
    dl->setAmbient( .0, .0, .0, 1 );
    dl->setDiffuse( .8f, .8f, .8f, 1.f );
    dl->setDirection(0,0,1);
    dl->setBeacon( b1n);

    // root
    root = OSG::Node::create();
    OSG::GroupUnrecPtr gr1 = OSG::Group::create();

    root->setCore( gr1 );
    root->addChild( t1n );
    root->addChild( dlight );

    // Load the file

    OSG::NodeUnrecPtr file = NULL;
    
    if(argc > 1)
        file = OSG::SceneFileHandler::the()->read(argv[1], NULL);
    
    if ( file == NULL )
    {
        std::cerr << "Couldn't load file, ignoring" << std::endl;

        file = OSG::makeSphere(4, 2.0);

    }

#if 0
    OSG::GeometryPtr pGeo = cast_dynamic<OSG::GeometryPtr>(file->getCore());
    
    if(pGeo == NULL && file->getNChildren() != 0)
    {
        pGeo = cast_dynamic<OSG::GeometryPtr>(file->getChild(0)->getCore());
    }

    if(pGeo == NULL)
    {
        fprintf(stderr, "no geo\n");
    }
#endif

//    OSG::GraphOpRefPtr op = OSG::GraphOpFactory::the()->create("Stripe");

//    op->traverse(file);
//    createOptimizedPrimitives(pGeo);
//    createSharedIndex(pGeo);
    
    OSG::Thread::getCurrentChangeList()->commitChanges();

//    file->dump();
    file->updateVolume();

#if 0
    const char *outFileName = "/tmp/foo1.osg";

    OSG::IndentFileOutStream outFileStream(outFileName);

    if( !outFileStream )
    {
        std::cerr << "Can not open output stream to file: "
                  << outFileName << std::endl;
        return -1;
    }

    std::cerr << "STARTING PRINTOUT:" << std::endl;
    OSGWriter writer( outFileStream, 4 );

    writer.write( file );

    outFileStream.close();

    OSG::SceneFileHandler::the()->write(file, "/tmp/foo.osb");
#endif    


//    return 0;


    OSG::Vec3f min,max;
    file->getVolume().getBounds( min, max );
    

    std::cout << "Volume: from " << min << " to " << max << std::endl;


    OSG::MultiCoreUnrecPtr pMCore = OSG::MultiCore::create();

    pCOver      = OSG::ChunkOverrideGroup::create();
    scene_trans = OSG::Transform::create();

    pMCore->addCore(scene_trans);
    pMCore->addCore(pCOver     );

    OSG::NodeUnrecPtr sceneTrN = OSG::Node::create();

    sceneTrN->setCore(pMCore);
    sceneTrN->addChild(file);


    dlight->addChild(sceneTrN);

    std::cerr << "Tree: " << std::endl;
//  root->dump();

    // Camera
    
    cam = OSG::PerspectiveCamera::create();

    cam->setBeacon( b1n );
    cam->setFov( OSG::osgDegree2Rad( 90 ) );
    cam->setNear( 0.1f );
    cam->setFar( 100000 );

    // Background
    OSG::SolidBackgroundUnrecPtr bkgnd = OSG::SolidBackground::create();

    bkgnd->setColor(OSG::Color3f(1,0,0));
    
    // Viewport

    vp = OSG::Viewport::create();

    vp->setCamera( cam );
    vp->setBackground( bkgnd );
    vp->setRoot( root );
    vp->setSize( 0,0, 1,1 );

#if 0
    OSG::UInt8 imgdata[] =
    {  
        64,64,64, 128,128,128, 192,192,192, 255,255,255 
    };
#endif

    pImg = OSG::Image::create();

    pImg->set(OSG::Image::OSG_RGB_PF, 128, 128); //, 1, 1, 1, 0.0, imgdata);

    tx1o = OSG::TextureObjChunk::create();
    tx1e = OSG::TextureEnvChunk::create();

    tx1o->setImage    (pImg      ); 
    tx1o->setMinFilter(GL_LINEAR );
    tx1o->setMagFilter(GL_LINEAR );
    tx1o->setWrapS    (GL_CLAMP );
    tx1o->setWrapT    (GL_CLAMP );
    tx1e->setEnvMode  (GL_REPLACE);

    OSG::SimpleMaterialUnrecPtr mat = OSG::SimpleMaterial::create();
    
    mat->setDiffuse(OSG::Color3f(1,1,1));
    mat->setLit    (false              );
    mat->addChunk  (tx1o               );
    mat->addChunk  (tx1e               );

    OSG::PolygonForegroundUnrecPtr pFG =  OSG::PolygonForeground::create();

    pFG->setMaterial(mat);

    OSG::MFPnt2f *pPos = pFG->editMFPositions();
    OSG::MFVec3f *pTex = pFG->editMFTexCoords();

    pPos->push_back(OSG::Pnt2f(0.0f, 0.0f));
    pPos->push_back(OSG::Pnt2f(0.3f, 0.0f));
    pPos->push_back(OSG::Pnt2f(0.3f, 0.3f));
    pPos->push_back(OSG::Pnt2f(0.0f, 0.3f));

    pTex->push_back(OSG::Vec3f(0.0f, 1.0f, 0.0f));
    pTex->push_back(OSG::Vec3f(1.0f, 1.0f, 0.0f));
    pTex->push_back(OSG::Vec3f(1.0f, 0.0f, 0.0f));
    pTex->push_back(OSG::Vec3f(0.0f, 0.0f, 0.0f));

    vp->addForeground(pFG);



    OSG::SimpleMaterialUnrecPtr matFgCheck = OSG::SimpleMaterial::create();
    
    matFgCheck->setDiffuse(OSG::Color3f(0,1,0));
    matFgCheck->setLit    (false              );

    OSG::PolygonForegroundUnrecPtr pFGCheck =  OSG::PolygonForeground::create();

    pFGCheck->setMaterial(matFgCheck);

    pPos = pFGCheck->editMFPositions();

    pPos->push_back(OSG::Pnt2f(0.6f, 0.0f));
    pPos->push_back(OSG::Pnt2f(0.9f, 0.0f));
    pPos->push_back(OSG::Pnt2f(0.9f, 0.3f));
    pPos->push_back(OSG::Pnt2f(0.6f, 0.3f));


    vp->addForeground(pFG);
    vp->addForeground(pFGCheck);
//    vp->dump();


    // Background
    OSG::SolidBackgroundUnrecPtr bkgndFBO = OSG::SolidBackground::create();

    bkgndFBO->setColor(OSG::Color3f(1.0,0.5,0.5));
    
    // Viewport

    vpFBO = OSG::FBOViewport::create();

    vpFBO->setCamera    (cam       );
    vpFBO->setBackground(bkgndFBO  );
    vpFBO->setRoot      (root      );
    vpFBO->setSize      (0, 0, 1, 1);

    vpFBO->addForeground(pFGCheck);

    OSG::FrameBufferObjectUnrecPtr pFBO = OSG::FrameBufferObject::create();

                               pTexBuffer   = OSG::TextureBuffer::create();
    OSG::RenderBufferUnrecPtr  pDepthBuffer = OSG::RenderBuffer ::create();

    pDepthBuffer->setInternalFormat(GL_DEPTH_COMPONENT24   );

    pTexBuffer->setTexture(tx1o);

    pFBO->setSize(128, 128);
    
    pFBO->setColorAttachment(pTexBuffer, 0);
    pFBO->setDepthAttachment(pDepthBuffer );

    pFBO->editMFDrawBuffers()->clear();
    pFBO->editMFDrawBuffers()->push_back(GL_COLOR_ATTACHMENT0_EXT);


    vpFBO->setFrameBufferObject(pFBO);



    // Window
    std::cout << "GLUT winid: " << winid << std::endl;


    GLint glvp[4];

    glGetIntegerv( GL_VIEWPORT, glvp );

    gwin = OSG::GLUTWindow::create();
    gwin->setGlutId(winid);
    gwin->setSize( glvp[2], glvp[3] );

    win = gwin;

    win->addPort(vpFBO   );
    win->addPort(vp      );

    win->init();

    // Action
    
    rentravact = OSG::RenderAction::create();
//    renact->setFrustumCulling(false);


    // tball

    OSG::Vec3f pos;
    pos.setValues(min[0] + ((max[0] - min[0]) * 0.5), 
                  min[1] + ((max[1] - min[1]) * 0.5), 
                  max[2] + ( max[2] - min[2] ) * 1.5 );
    
    float scale = (max[2] - min[2] + max[1] - min[1] + max[0] - min[0]) / 6;

    OSG::Pnt3f tCenter(min[0] + (max[0] - min[0]) / 2,
                       min[1] + (max[1] - min[1]) / 2,
                       min[2] + (max[2] - min[2]) / 2);

    fprintf(stderr, "Startpos : %f %f %f\n", pos[0], pos[1], pos[2]);

    tball.setMode( OSG::Trackball::OSGObject );
    tball.setStartPosition( pos, true );
    tball.setSum( true );
    tball.setTranslationMode( OSG::Trackball::OSGFree );
    tball.setTranslationScale(scale);
    tball.setRotationCenter(tCenter);

    // run...
    
    pPoly = OSG::PolygonChunk::create();

    pCOver->subChunk(pPoly);

    return 0;
}
// Setup the part of the scene rooted at animRoot
// This includes a file to animate, a beacon for a light,
// and a staged core to render this subtree from the position
// of the light.
void initAnimSetup(int argc, char **argv)
{
    // beacon for light and stage camera
    OSG::GroupNodeRefPtr beacon = OSG::GroupNodeRefPtr::create();

    // transformation for beacon
    cam_transScene   = OSG::TransformNodeRefPtr::create();
    cam_transScene.node()->addChild(beacon);

    // light
    OSG::DirectionalLightNodeRefPtr dlight = 
        OSG::DirectionalLightNodeRefPtr::create();

    dlight->setAmbient  (.3f, .3f, .3f, 1);
    dlight->setDiffuse  ( 1,  1,  1, 1);
    dlight->setDirection( 0,  0,  1   );
    dlight->setBeacon   (beacon       );

    // animRoot
    animRoot = OSG::GroupNodeRefPtr::create();
    animRoot.node()->addChild(cam_transScene   );

    // Load the file and put it in the graph
    // under the sceneXform node.
    OSG::NodeUnrecPtr file = NULL;

    if(argc > 1)
    { file = OSG::SceneFileHandler::the()->read(argv[1]); }

    if(file == NULL)
    {
        std::cerr << "Couldn't load file, ignoring" << std::endl;
        file = OSG::makeTorus(.5, 2, 16, 16);
    }

    OSG::Vec3f min,max;
    OSG::commitChanges();
    file->updateVolume();
    file->dump();
    file->getVolume().getBounds(min, max);

    std::cout << "Volume: from " << min << " to " << max << std::endl;
    sceneTrans.setValues(min[0] + ((max[0] - min[0]) * 0.5),
                         min[1] + ((max[1] - min[1]) * 0.5),
                         max[2] + ( max[2] - min[2]) * 4.5 );


    sceneXform = OSG::TransformNodeRefPtr::create();
    sceneXform.node()->addChild(file);

    OSG::NodeUnrecPtr pBoxNode = OSG::makeBox(1, 1, 1, 5, 5, 5);

    pBoxNode->setTravMask(pBoxNode->getTravMask() & 0x0001);

    sceneXform.node()->addChild(pBoxNode);

    dlight.node()->addChild(sceneXform);


    // ---- STAGE RENDERING SETUP --- //
    // Camera: setup camera to point from beacon (light pos)
    //   with a 90deg FOV to render the scene
    OSG::PerspectiveCameraUnrecPtr stage_cam = OSG::PerspectiveCamera::create();

    stage_cam->setBeacon(beacon);
    stage_cam->setFov   (OSG::osgDegree2Rad(90));
    stage_cam->setNear  (0.1f);
    stage_cam->setFar   (100000);


    // Background
    OSG::SolidBackgroundUnrecPtr bkgnd = OSG::SolidBackground::create();
    bkgnd->setColor(OSG::Color3f(0,1,0));

    // FBO setup
    pFBO         = OSG::FrameBufferObject::create();
    pTexBuffer   = OSG::TextureBuffer::create();

#ifdef USE_DEPTH_TEXTURE
    OSG::TextureBufferUnrecPtr     pDepthBuffer = OSG::TextureBuffer::create();
    pDepthBuffer->setTexture(txDepth);
#else
    OSG::RenderBufferUnrecPtr      pDepthBuffer = OSG::RenderBuffer ::create();
    pDepthBuffer->setInternalFormat(GL_DEPTH_COMPONENT24   );
#endif

    
    pTexBuffer->setTexture (tx1o);
    pTexBuffer->setReadBack(true);

    pFBO->setSize(512, 512);
    pFBO->setColorAttachment(pTexBuffer, 0);
    pFBO->setDepthAttachment(pDepthBuffer );

    pFBO->editMFDrawBuffers()->clear();
    pFBO->editMFDrawBuffers()->push_back(GL_COLOR_ATTACHMENT0_EXT);

    // Stage core setup
    OSG::SimpleStageNodeRefPtr pStage    = OSG::SimpleStageNodeRefPtr::create();
    pStage->setRenderTarget(pFBO );
    pStage->setCamera      (stage_cam  );
    pStage->setBackground  (bkgnd);

    pStage->addPreRenderFunctor (&testPreRenderCB, "" );
    pStage->addPostRenderFunctor(&testPostRenderCB, "");

    // Setup sub-tree visitor
    // - This will setup a graph that will render a subtree during traversal
    pVisit = OSG::VisitSubTreeNodeRefPtr::create();
    pVisit->setSubTreeRoot(dlight);

    pStage.node()->addChild(pVisit);
    animRoot.node()->addChild(pStage);
    animRoot.node()->addChild(dlight);
}