package demo;

import javax.media.opengl.*;

import jocode.*;

/**
 * Use setMaterial(), setLight() and makeTexture() to control light and material properties.
 * <P>
 * napier at potatoland dot org
 */
public class DemoLight extends JOApp {
    // Handles for textures
    int marbleTextureHandle = 0;
    int groundTextureHandle = 0;
    // Light position: if last value is 0, then this describes light direction.  If 1, then light position.
    float lightPosition1[]= { 0f, 0f, 0f, 1f };
    float lightPosition2[]= { 0f, -10f, 0f, 0f };
    float lightPosition3[]= { 0f, 0f, 0f, 1f };
    // Rotation of sphere
    float rotation=0f;
    // display lists
    int sphereDL=0, cubeDL=0;

    //------------------------------------------------------------------------
    // Run main loop of application.  Handle mouse and keyboard input.
    //------------------------------------------------------------------------

    public static void main(String args[]) {
    	DemoLight demo = new DemoLight();
        windowTitle   = "GLApp Simple Scene";
        displayWidth  = 800;
        displayHeight = 600;
        demo.run();  // will call init(), render(), mouse event functions
    }

    /**
     * Initialize the scene.  Called by GLApp.run()
     */
    @Override
    public void setup() {
        // Create sphere texture
        marbleTextureHandle = makeTexture("images/marble.jpg");

        // Create texture for ground plane
        groundTextureHandle = makeTexture("images/mahog_texture.jpg");

        // setup perspective
        setPerspective();

        // Create a point light (white)
        setLight(GL.GL_LIGHT1,
        		 new float[] { 1.0f, 1.0f, 1.0f, 1.0f },     // diffuse color
        		 new float[] { 0.2f, 0.2f, 0.2f, 1.0f },     // ambient
        		 new float[] { 1.0f, 1.0f, 1.0f, 1.0f },     // specular
        		 lightPosition1);                            // position

        // Create a directional light (dark red, to simulate reflection off wood surface)
        setLight(GL.GL_LIGHT2,
        		 new float[] { 0.95f, 0.35f, 0.15f, 1.0f },  // diffuse color
        		 new float[] { 0.0f,  0.0f,  0.0f,  1.0f },  // ambient
        		 new float[] { 0.03f, 0.0f,  0.0f,  1.0f },  // specular
        		 lightPosition2);                            // position (pointing up)

        // Create a point light (dark blue, to simulate reflection off wood surface)
        setLight(GL.GL_LIGHT3,
        		 new float[] { 0.35f, 0.45f, 0.95f, 1.0f },  // diffuse color
        		 new float[] { 0.0f,  0.0f,  0.0f,  1.0f },  // ambient
        		 new float[] { 0.3f,  0.4f,  0.7f,  1.0f },  // specular
        		 lightPosition3 );                           // position (pointing up)

        // no overall scene lighting
        setAmbientLight(new float[] { 0.0f, 0.0f, 0.0f, 0.0f });

        // make a sphere displaylist
        sphereDL = beginDisplayList();
        renderSphere(48);    // 48 facets: pretty smooth
        endDisplayList();
        
        // make a cube displaylist
        cubeDL = beginDisplayList();
        renderCube(10,40);   // 10 units, 40 divisions
        endDisplayList();
        
        // enable lighting and texture rendering
        gl.glEnable(GL.GL_LIGHTING);
        gl.glEnable(GL.GL_TEXTURE_2D);

        // select model view for subsequent transforms
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    /**
     * Render one frame.  Called by GLApp.run().
     */
    @Override
    public void draw() {
    	// rotate 25 degrees per second
        rotation += 25f * getSecondsPerFrame();

        // clear depth buffer and color buffers
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

        // select model view for subsequent transforms
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();

        // set the viewpoint
        glu.gluLookAt(0f, 3f, 15f,  // where is the eye
        			0f, -1f, 0f,    // what point are we looking at
        			0f, 1f, 0f);    // which way is up

        //---------------------------------------------------------------
        // desktop
        //---------------------------------------------------------------
        
        // dark reddish material
        setMaterial( new float[] {0.8f, 0.3f, 0.2f, 1.0f}, .2f); 

        // enable texture
        gl.glBindTexture(GL.GL_TEXTURE_2D, groundTextureHandle);

        // draw the ground plane
        gl.glPushMatrix();
        {
            gl.glTranslatef(0f, -7f, 0f);  // down a bit
            callDisplayList(cubeDL);
        }
        gl.glPopMatrix();

        // orbit
        gl.glRotatef(rotation, 0,1,0);
        gl.glTranslatef(3,0,0);

        gl.glRotatef(rotation/2, 0,1,0);
        gl.glTranslatef(-2,0,0);

        //---------------------------------------------------------------
        // glowing white ball
        //---------------------------------------------------------------
        
        // for point lights set position each frame so light moves with scene
        // white light at same position as marble ball
        setLightPosition(GL.GL_LIGHT1, lightPosition1);
        
        // glowing white material
        setMaterial(
        		new float[] {1.0f, 1.0f, 1.0f, 1.0f},   // diffuse color
        		new float[] {1.0f, 1.0f, 1.0f, 1.0f},   // ambient
        		new float[] {0.0f, 0.0f, 0.0f, 1.0f},   // specular
        		new float[] {1.0f, 1.0f, 1.0f, 1.0f},   // emissive
        		0f);        // not shiny

        // enable texture
        gl.glBindTexture(GL.GL_TEXTURE_2D, marbleTextureHandle);

        // draw marble sphere
        gl.glPushMatrix();
        {
            gl.glScalef(.5f, .5f, .5f);    // make it smaller
            callDisplayList(sphereDL);       // draw the sphere display list
        }
        gl.glPopMatrix();

        // orbit
        gl.glRotatef(rotation*1.4f, 0,1,0);
        gl.glTranslatef(4,0,0);

        //---------------------------------------------------------------
        // shiny blue ball
        //---------------------------------------------------------------
        
        // shiny dark blue material
        setMaterial(new float[] {0.3f, 0.3f, 0.6f, 1.0f}, .9f); 

        // set blue light at same spot as blue sphere
        setLightPosition(GL.GL_LIGHT3, lightPosition3);

        // no texture (texture handle 0)
        gl.glBindTexture(GL.GL_TEXTURE_2D, 0);

        // Draw sphere
        gl.glPushMatrix();
        {
            gl.glScalef(1.6f, 1.6f, 1.6f);  // make it smaller
            callDisplayList(sphereDL);
        }
        gl.glPopMatrix();
    }
}