// react to keys
void keyboard(unsigned char k, int x, int y)
{
    switch(k)
    {
        case 27:
        case 'q':
            _scene       = NULL;
            _point1_core = NULL;
            _point2_core = NULL;
            _point3_core = NULL;

            point1_beacon = NULL;
            point2_beacon = NULL;
            point3_beacon = NULL;

            _mgr          = NULL;

            OSG::osgExit();

            exit(1);
        break;
        case 'w':
            OSG::SceneFileHandler::the()->write(_scene, "scene.osb.gz", true);
            printf("wrote scene.osb.gz\n");
        break;
        case '1':
        {
            if(_point1_core->getOn() == false)
                _point1_core->setOn(true);
            else
                _point1_core->setOn(false);
            break;
        }

        case '2':
        {
            if(_point2_core->getOn() == false)
                _point2_core->setOn(true);
            else
                _point2_core->setOn(false);
            break;
        }

        case '3':
        {
            if(_point3_core->getOn() == false)
                _point3_core->setOn(true);
            else
                _point3_core->setOn(false);
            break;
        }
    }

    glutPostRedisplay();
}
// Initialize GLUT & OpenSG and set up the scene
int doMain(int argc, char **argv)
{
    printf("Press key '1', '2', or '3' to toggle the light sources.\n");
    // OSG init
    OSG::osgInit(argc,argv);

    // GLUT init
    int winid = setupGLUT(&argc, argv);

    // the connection between GLUT and OpenSG
    OSG::GLUTWindowUnrecPtr gwin= OSG::GLUTWindow::create();

    gwin->setGlutId(winid);
    gwin->setSize( 800, 800 );
    gwin->init();

    // Create the shader material

    OSG::ChunkMaterialUnrecPtr cmat = OSG::ChunkMaterial::create();

    OSG::MaterialChunkUnrecPtr matc = OSG::MaterialChunk::create();

    matc->setAmbient(OSG::Color4f(0.1f, 0.1f, 0.1f, 1.0f));
    matc->setDiffuse(OSG::Color4f(0.3f, 0.3f, 0.3f, 1.0f));
    matc->setSpecular(OSG::Color4f(0.8f, 0.8f, 0.8f, 1.0f));
    matc->setShininess(100);
    matc->setLit(true);

    OSG::ShaderProgramChunkUnrecPtr shl = OSG::ShaderProgramChunk::create();

    OSG::ShaderProgramUnrecPtr shl_vp = 
        OSG::ShaderProgram::createVertexShader();

    shl_vp->setProgram(_vp_program);

    shl->addShader(shl_vp);

    OSG::ShaderProgramUnrecPtr shl_fp = 
        OSG::ShaderProgram::createFragmentShader();

    shl_fp->setProgram(_fp_program);

    shl->addShader(shl_fp);

    shl_vp->addProceduralVariable    ("Light0Active", &light0Active);
    shl_vp->addProceduralVariable    ("Light1Active", &light1Active);
    shl_vp->addNodeProceduralVariable("Light2Active", &light2Active);

    cmat->addChunk(matc);
    cmat->addChunk(shl);

    // create root node
    _scene = OSG::Node::create();

    // create two light sources.

    OSG::TransformUnrecPtr point1_trans;

    OSG::NodeUnrecPtr point1        = 
        OSG::makeCoredNode<OSG::PointLight>(&_point1_core);
    point1_beacon = OSG::makeCoredNode<OSG::Transform >(&point1_trans);

    point1_trans->editMatrix().setTranslate(-10.0, 5.0, 5.0);

    _point1_core->setAmbient(0.0f, 0.0f, 0.0f , 1.0f);
    _point1_core->setDiffuse(1.0f, 0.0f, 0.0f, 1.0f);
    _point1_core->setSpecular(1.0f, 1.0f, 1.0f, 1.0f);
    _point1_core->setBeacon(point1_beacon);
    _point1_core->setOn(true);


    OSG::TransformUnrecPtr point2_trans;

    OSG::NodeUnrecPtr point2        =
        OSG::makeCoredNode<OSG::PointLight>(&_point2_core);
    point2_beacon = OSG::makeCoredNode<OSG::Transform >(&point2_trans);

    point2_trans->editMatrix().setTranslate(10.0, 5.0, 5.0);

    _point2_core->setAmbient(0.0f, 0.0f, 0.0f, 1.0f);
    _point2_core->setDiffuse(0.0f, 1.0f, 0.0f, 1.0f);
    _point2_core->setSpecular(1.0f, 1.0f, 1.0f, 1.0f);
    _point2_core->setBeacon(point2_beacon);
    _point2_core->setOn(true);

    point1->addChild(point2);
    
    OSG::TransformUnrecPtr point3_trans;

    OSG::NodeUnrecPtr point3        = 
        OSG::makeCoredNode<OSG::PointLight>(&_point3_core);
    
    point3_beacon = OSG::makeCoredNode<OSG::Transform >(&point3_trans);

    point3_trans->editMatrix().setTranslate(0.0, -12.0, 5.0);

    _point3_core->setAmbient(0.0f, 0.0f, 0.0f, 1.0f);
    _point3_core->setDiffuse(0.5f, 0.0f, 1.0f, 1.0f);
    _point3_core->setSpecular(1.0f, 1.0f, 1.0f, 1.0f);
    _point3_core->setBeacon(point3_beacon);
    _point3_core->setOn(true);

    point2->addChild(point3);


    // create a sphere.
    OSG::GeometryUnrecPtr geo = OSG::makeLatLongSphereGeo (100, 100, 1.0);

    geo->setMaterial(cmat);


    OSG::NodeUnrecPtr sphere = OSG::makeNodeFor(geo);

    point3->addChild(sphere);


    _scene->setCore(OSG::Group::create());
    _scene->addChild(point1);

    // create the SimpleSceneManager helper
    _mgr = OSG::SimpleSceneManager::create();

    // tell the manager what to manage
    _mgr->setWindow(gwin );
    _mgr->setRoot(_scene);

    _mgr->turnHeadlightOff();

    // show the whole scene
    _mgr->showAll();

    // enable local lights.
//    OSG::RenderAction *ract = 
//        dynamic_cast<OSG::RenderAction *>(_mgr->getRenderAction());

//    ract->setLocalLights(true);

    return 0;
}
// react to keys
void keyboard(unsigned char k, int x, int y)
{
    switch(k)
    {
        case 27:
        case 'q':
            _scene       = NULL;
            _point1_core = NULL;
            _point2_core = NULL;
            _point3_core = NULL;

            shl          = NULL;

            delete _mgr;

            exit(1);
        break;
        case 'w':
            OSG::SceneFileHandler::the()->write(_scene, "scene.osb.gz", true);
            printf("wrote scene.osb.gz\n");
        break;
        case '1':
        {
            if(_point1_core->getOn() == false)
                _point1_core->setOn(true);
            else
                _point1_core->setOn(false);
            break;
        }

        case '2':
        {
            if(_point2_core->getOn() == false)
                _point2_core->setOn(true);
            else
                _point2_core->setOn(false);
            break;
        }

        case '3':
        {
            if(_point3_core->getOn() == false)
                _point3_core->setOn(true);
            else
                _point3_core->setOn(false);
            break;
        }

        case 'i':
            shl->subUniformParameter("OSGLight0Active");
            break;
        case 'I':
            shl->setUniformParameter("OSGLight0Active", 0);
            break;
        case 'o':
            shl->subUniformParameter("OSGLight1Active");
            break;
        case 'O':
            shl->setUniformParameter("OSGLight1Active", 0);
            break;
        case 'p':
            shl->subUniformParameter("OSGLight2Active");
            break;
        case 'P':
            shl->setUniformParameter("OSGLight2Active", 0);
            break;
    }

    glutPostRedisplay();
}