// Initialize GLUT & OpenSG and set up the scene
int main(int argc, char **argv)
{
    printf("Usage: testCGShader <filename.vp> <filename.fp>\n");

    if( argc < 3 )
        return 0;
    
    // 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.1, 0.1, 0.1, 1.0));
    matc->setDiffuse(OSG::Color4f(0.3, 0.3, 0.3, 1.0));
    matc->setSpecular(OSG::Color4f(0.8, 0.8, 0.8, 1.0));
    matc->setShininess(100);
    matc->setLit(true);

    OSG::SHLChunkUnrecPtr shl = OSG::SHLChunk::create();

    shl->readVertexProgram(argv[1]);
    shl->readFragmentProgram(argv[2]);

    cmat->addChunk(shl);


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

    // create torus
    OSG::GeometryUnrecPtr geo = OSG::makeTorusGeo(.8, 1.8, 128, 128);
    geo->setMaterial(cmat);

    OSG::NodeUnrecPtr torus = OSG::Node::create();
    torus->setCore(geo);

    // add torus to scene
    OSG::GroupUnrecPtr group = OSG::Group::create();
    _scene->setCore(group);
    _scene->addChild(torus);

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

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

    /*
    // create point headlight
    _mgr->turnHeadlightOff();
    NodePtr headlight = _mgr->getHighlight();
    PointLightPtr light    = PointLight::create();
    beginEditCP(light);
        light->setAmbient  (.3, .3, .3, 1);
        light->setDiffuse  ( 1,  1,  1, 1);
        light->setSpecular ( 1,  1,  1, 1);
        light->setBeacon   (_mgr->getCamera()->getBeacon());
    endEditCP(light);
    beginEditCP(_scene);
        _scene->setCore(light);
    endEditCP(_scene);
    */

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

    // GLUT main loop
    glutMainLoop();

    return 0;
}
// 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.1, 0.1, 0.1, 1.0));
    matc->setDiffuse(OSG::Color4f(0.3, 0.3, 0.3, 1.0));
    matc->setSpecular(OSG::Color4f(0.8, 0.8, 0.8, 1.0));
    matc->setShininess(100);
    matc->setLit(true);

    OSG::SHLChunkUnrecPtr shl = OSG::SHLChunk::create();

    shl->setVertexProgram(_vp_program);
    shl->setFragmentProgram(_fp_program);

    shl->addParameterCallback("OSGL0SpecialParameter", light0Active);
    shl->addParameterCallback("OSGL1SpecialParameter", light1Active);
    shl->addParameterCallback("OSGL2SpecialParameter", 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 = new OSG::SimpleSceneManager;

    // 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;
}
// Initialize GLUT & OpenSG and set up the scene
int main(int argc, char **argv)
{
    printf("Usage: testCGShader [normal map filename]\n");
    const char *normal_map_img_name = "opensg_logoDOT3.png";

    OSG::Color4f tmp;

    if( argc > 1 )
        normal_map_img_name = argv[1];

    // 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

    // Read the image for the normal texture
    OSG::ImageUnrecPtr normal_map_img = OSG::Image::create();
    if(!normal_map_img->read(normal_map_img_name))
    {
        fprintf(stderr, "Couldn't read normalmap texture '%s'!\n", normal_map_img_name);
        return 1;
    }

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

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

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

    OSG::SHLChunkUnrecPtr shl = OSG::SHLChunk::create();

    shl->setVertexProgram(_vp_program);
    shl->setFragmentProgram(_fp_program);

    OSG::TextureObjChunkUnrecPtr tex_normal_map     = 
        OSG::TextureObjChunk::create();
    OSG::TextureEnvChunkUnrecPtr tex_normal_map_env = 
        OSG::TextureEnvChunk::create();

    tex_normal_map->setImage(normal_map_img);
    tex_normal_map->setMinFilter(GL_LINEAR_MIPMAP_LINEAR);
    tex_normal_map->setMagFilter(GL_LINEAR);
    tex_normal_map->setWrapS(GL_REPEAT);
    tex_normal_map->setWrapT(GL_REPEAT);
    tex_normal_map_env->setEnvMode(GL_MODULATE);

        //cmat->addChunk(matc);
    cmat->addChunk(shl);
    cmat->addChunk(tex_normal_map);
    cmat->addChunk(tex_normal_map_env);


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

    // create geometry
    //GeometryPtr geo = makeLatLongSphereGeo (100, 100, 1.0);
    OSG::GeometryUnrecPtr geo = OSG::makePlaneGeo(1.0, 1.0, 100, 100);

    geo->setMaterial(cmat);

    OSG::NodeUnrecPtr torus = OSG::Node::create();
    torus->setCore(geo);

    // add torus to scene
    OSG::GroupUnrecPtr group = OSG::Group::create();

    _scene->setCore(group);
    _scene->addChild(torus);

    // create the SimpleSceneManager helper
    _mgr = new OSG::SimpleSceneManager;

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

    /*
    // create point headlight
    _mgr->turnHeadlightOff();
    NodePtr headlight = _mgr->getHighlight();
    PointLightPtr light    = PointLight::create();
    beginEditCP(light);
        light->setAmbient  (.3, .3, .3, 1);
        light->setDiffuse  ( 1,  1,  1, 1);
        light->setSpecular ( 1,  1,  1, 1);
        light->setBeacon   (_mgr->getCamera()->getBeacon());
    endEditCP(light);
    beginEditCP(_scene);
        _scene->setCore(light);
    endEditCP(_scene);
    */

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

    // GLUT main loop
    glutMainLoop();

    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();
}
// Initialize GLUT & OpenSG and set up the scene
int doMain(int argc, char **argv)
{
    // 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::SHLChunkUnrecPtr shl = OSG::SHLChunk::create();

    shl->setProgramParameter(GL_GEOMETRY_INPUT_TYPE_EXT, 
                             GL_TRIANGLES);
    shl->setProgramParameter(GL_GEOMETRY_OUTPUT_TYPE_EXT, 
                             GL_TRIANGLE_STRIP);
    shl->setProgramParameter(GL_GEOMETRY_VERTICES_OUT_EXT, 6);

    shl->setVertexProgram(_vertex_shader);
    shl->setFragmentProgram(_fragment_shader);
    shl->setGeometryProgram(_geometry_shader);

    cmat->addChunk(shl);

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

    // create torus
    OSG::GeometryUnrecPtr geo = OSG::makeTorusGeo(.8, 1.8, 128, 128);

    geo->setMaterial(cmat);

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

    torus->setCore(geo);

    // add torus to scene
    OSG::GroupUnrecPtr group = OSG::Group::create();

    _scene->setCore(group);
    _scene->addChild(torus);

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

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

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

    return 0;
}