//-----------------------------------------------------------------------------
// file: ogl.cpp
// desc: starting point
//
// author: Ge Wang (gewang@cs.princeton.edu)
//         Perry R. Cook (prc@cs.princeton.edu)
//         Brandon Braunstein (bbraunst@princeton.edu)  
//         Douglas Corey Campbell (campbell@princeton.edu)
//         Candice Hebden (chebden@princeton.edu)
//         Paul Simbi (psimbi@princeton.edu)  
// date: autumn 2002
//-----------------------------------------------------------------------------
#include <GL/glut.h>

// width and height of the window
GLsizei g_width = 800;
GLsizei g_height = 400;

// light position
GLfloat g_light0_pos[4] = { 4.0f, 4.0f, 4.0f, 1.0f };

// function prototypes
void initialize();
void idleFunc( );
void displayFunc( );
void reshapeFunc( GLsizei width, GLsizei height );
void keyboardFunc( unsigned char, int, int );
void mouseFunc( int button, int state, int x, int y );




//-----------------------------------------------------------------------------
// Name: main( )
// Desc: entry point
//-----------------------------------------------------------------------------
int main( int argc, char ** argv )
{
    // initialize GLUT
    glutInit( &argc, argv );
    // double buffer, use rgb color, enable depth buffer
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
    // initialize the window size
    glutInitWindowSize( g_width, g_height );
    // set the window postion
    glutInitWindowPosition( 100, 100 );
    // create the window
    glutCreateWindow( "Our OpenGL Sample" );

    // set the idle function - called when idle
    glutIdleFunc( idleFunc );
    // set the display function - called when redrawing
    glutDisplayFunc( displayFunc );
    // set the reshape function - called when client area changes
    glutReshapeFunc( reshapeFunc );
    // set the keyboard function - called on keyboard events
    glutKeyboardFunc( keyboardFunc );
    // set the mouse function - called on mouse stuff
    glutMouseFunc( mouseFunc );

    // do our own initialization
    initialize();

    // let GLUT handle the current thread from here
    glutMainLoop();

    return 0;
}




//-----------------------------------------------------------------------------
// Name: idleFunc( )
// Desc: callback from GLUT
//-----------------------------------------------------------------------------
void idleFunc( )
{
    // render the scene
    glutPostRedisplay( );
}




//-----------------------------------------------------------------------------
// Name: keyboardFunc( )
// Desc: key event
//-----------------------------------------------------------------------------
void keyboardFunc( unsigned char key, int x, int y )
{
    switch( key )
    {
    case 'q':
        exit( 0 );
    break;
    }

    glutPostRedisplay( );
}




//-----------------------------------------------------------------------------
// Name: mouseFunc( )
// Desc: handles mouse stuff
//-----------------------------------------------------------------------------
void mouseFunc( int button, int state, int x, int y )
{
    if( button == GLUT_LEFT_BUTTON )
    {
    }
    else if ( button == GLUT_RIGHT_BUTTON )
    {
    }

    glutPostRedisplay( );
}




//-----------------------------------------------------------------------------
// Name: initialize( )
// Desc: init
//-----------------------------------------------------------------------------
void initialize()
{
    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    // enable depth
    glEnable( GL_DEPTH_TEST );
    // set the front faces of polygons
    glFrontFace( GL_CCW );
    // set fill mode
    glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

    // set the shading model to 'smooth'
    glShadeModel( GL_SMOOTH );

    // enable lighting
    glEnable( GL_LIGHTING );
    // enable light 0
    glEnable( GL_LIGHT0 );
    // enable lighting for front
    glLightModeli( GL_FRONT, GL_TRUE );
    // enable color
    glEnable( GL_COLOR_MATERIAL );
    // material have diffuse and ambient lighting 
    glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
}




//-----------------------------------------------------------------------------
// Name: reshapeFunc( )
// Desc: called when window size changes
//-----------------------------------------------------------------------------
void reshapeFunc( GLsizei w, GLsizei h )
{
    // save the new window size
    g_width = w; g_height = h;
    // map the view port to the client area
    glViewport( 0, 0, w, h );
    // set the matrix mode to project
    glMatrixMode( GL_PROJECTION );
    // load the identity matrix
    glLoadIdentity( );
    // create the viewing frustum
    gluPerspective( 70.0, (GLfloat) w / (GLfloat) h, .1, 300.0 );
    // set the matrix mode to modelview
    glMatrixMode( GL_MODELVIEW );
    // load the identity matrix
    glLoadIdentity( );
    // position the view point
    gluLookAt( 0.0f, 0.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f );

    // set the position of the lights
    glLightfv( GL_LIGHT0, GL_POSITION, g_light0_pos );
}




//-----------------------------------------------------------------------------
// Name: displayFunc( )
// Desc: draw
//-----------------------------------------------------------------------------
void displayFunc()
{
    // clear the color and depth buffers
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    static double r = 0.0f;
    // push the current modelview matrix
    glPushMatrix();
    // translate
    glTranslatef( 0.0f, 0.0f, 1.0f );
    // rotate
    glRotatef( r, 1.0f, 0.0f, 0.0f );
    r += .1f;
    // color
    glColor3f( 1.0f, 1.0f, 0.0f );
    // draw stuff
    glutSolidSphere( .5f, 16, 16 );
    // pop
    glPopMatrix();

    // flush and swap the buffers
    glFlush();
    glutSwapBuffers();
}

