package classwork;

import javax.media.opengl.*;
import jocode.*;
import jomodel.*;

/**
 * GLART_4_orbit_lights.java
 *
 * Orbit a light source around two spheres.
 *
 * Set the light position after glTranslate/glRotate to move the light.
 *
 * Use glEnable(GL.GL_NORMALIZE) to force all normals to a length of 1.
 * This is critical to insure consistent lighting when spheres are
 * scaled to different sizes (normals will be scaled too!).
 *
 * Use the EMISSIVE material property to create a glowing sphere.
 *
 * Use a display list to optimize the sphere rendering.
 */
public class GLART_4_orbit_lights extends JOApp {
 	float rotation = 0f;

    // Material for planet
    JOMaterial material = new JOMaterial();

    // Material, glowing (for "light")
    JOMaterial materialE = new JOMaterial();

    /**
     * Main function just creates and runs the application.
     */
    public static void main(String args[]) {
    	GLART_4_orbit_lights app = new GLART_4_orbit_lights();
        app.run();
    }

    /**
     * Initialize OpenGL
     *
     */
    public void setup() {
        // Set a basic perspective view
    	setPerspective();

        // turn depth testing on
        gl.glEnable(GL.GL_DEPTH_TEST);

        // turn lighting on (does not create a light, have to do that below)
        gl.glEnable(GL.GL_LIGHTING);

        // Tell OpenGL to force all normal lengths to 1,
        // so light illuminates all surfaces evenly
        gl.glEnable(GL.GL_NORMALIZE);

        //-----------------------------------------------
        // Create light
        //-----------------------------------------------
        
        // color of light source
        float lightDiffuse[]  = new float[] { 1f, 1f, .5f, 1f };    // direct light
        float lightSpecular[] = new float[] { 1f, 1f, .5f, 1f };    // highlight
        float lightAmbient[]  = new float[] { .2f, .2f, .1f, 1f };  // scattered light
        // light position: if last value is 0, then this describes light direction.  If 1, then light position.
        float lightPosition[] = new float[] { -4f, 4f, 4, 1f };
        // Create a light
        // diffuse is the color of direct light from this light source
        // ambient is the color of reflected light from this source
        // position is where the light is, or it's direction
        setLight( GL.GL_LIGHT1, lightDiffuse, lightAmbient, lightSpecular, lightPosition );

        // overall scene lighting
        float ambient[]       = new float[] { .4f, .4f, .5f, 1f };
        setAmbientLight(ambient);

        //-----------------------------------------------
        // Create 2 Materials
        //-----------------------------------------------
        
        // Red material settings
        float mtlDiffuse[]    = { 1f, 0f, 0f, 1f };    // red
        float mtlAmbient[]    = { .5f, 0f, 0f, 1f };    // red
        float mtlSpecular[]   = { .6f, .6f, .6f, 1f };  // light gray: reflective
        float mtlShininess    = 100f;   // 0=no highlight,  127=sharp highlight
        material.setDiffuse(mtlDiffuse);
        material.setAmbient(mtlAmbient);
        material.setSpecular(mtlSpecular);
        material.setShininess(mtlShininess);
        material.apply();

        // make a glowing material for the "light"
        float mtlEmissive[]   = { 1f, 1f, .4f, 1f };    // yellow/white
        materialE.setEmission(mtlEmissive);
    }

    /**
     * Render the scene.
     */
    public void draw() {
     	rotation += .5f;
     	
        // Clear screen and depth buffer
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

        // Select The Modelview Matrix (controls model orientation)
        gl.glMatrixMode(GL.GL_MODELVIEW);

        // Reset the Modelview matrix
        // this resets the coordinate system to center of screen
        gl.glLoadIdentity();

        // Where is the 'eye'
        glu.gluLookAt(
            0f, 2f, 20f,    // eye position
            0f, 0f, 0f,    // target to look at
            0f, 1f, 0f);   // which way is up

        // 1: draw sphere at center
        gl.glPushMatrix();
		{
			gl.glScalef(3f, 3f, 3f);
			renderSphere(48);   // 48 divisions around sphere: smoother
		}
        gl.glPopMatrix();

		// rotate coord system around Y
        // all rendering below this point will be rotated
		gl.glRotatef(rotation, 0,1,0);
		// shift coordinate system right away from center
		gl.glTranslatef(9, 0, 0);

		// 2: draw orbiting sphere
        gl.glPushMatrix();
		{
			// shrink it down
			gl.glScalef(1.5f, 1.5f, 1.5f);
			renderSphere();
		}
		gl.glPopMatrix();

	    // 3: draw white sphere and set light position to that position
	    gl.glPushMatrix();
		{
			// rotate moon around earth
			gl.glRotatef(rotation * 2.3f, 0, 1, 0);
			// shift coordinate system right away from earth
			gl.glTranslatef(4f, 0, 0);
			// Set light position (will be transformed just like a vertex)
			setLightPosition(GL.GL_LIGHT1, 0, 0, 0);
			// shrink
			gl.glScalef(.3f, .3f, .3f);
			// turn on light material (glowing), draw small sphere
			materialE.apply();
			renderSphere();
			// revert to planet material
	        material.apply();
		}
	    gl.glPopMatrix();
    }

    /**
     * Reshape() is called when window is resized.  Reset the viewport to the new window
     * dimensions and call setPerspective() to reset the perspective view.  This will use
     * the new aspect ratio of the window so the scene will not be squashed or stretched.
     */
    public void reshape(int newDisplayWidth, int newDisplayHeight) {
    	setViewport(0,0,newDisplayWidth,newDisplayHeight);
    	setPerspective();
    }
}
