

import java.awt.*;
import java.awt.event.*;
import javax.media.opengl.awt.GLJPanel;
import javax.swing.*;
import javax.media.opengl.*;
import javax.media.opengl.glu.GLU;
import com.jogamp.opengl.util.gl2.GLUT;

/**
 * A panel of type Avatar displays a "world" consisting of
 * a large disk with a variety of objects standing at various
 * positions on the disk.  You are in this world, standing on
 * the disk, and you can move around using the arrow keys.
 * The HOME key returns you to your original position and
 * orientation.  The main() routine just opens a window that
 * shows an Avatar panel.
 */
public class Avatar extends GLJPanel implements GLEventListener, KeyListener {

	public static void main(String[] args){
		JFrame window = new JFrame("USE ARROW KES TO MOVE AND ROTATE");
		GLJPanel content = new Avatar();
		window.setContentPane(content);
		window.pack();
		window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		window.setVisible(true);
		System.out.println("The up and down arrow keys will move your viewpoint.");
		System.out.println("forwards and backwards.  The left and right arrow keys");
		System.out.println("will rotate you to the left or to the right.");
		System.out.println("The HOME key restores the original point of view.");
		content.requestFocusInWindow();
	}
	
	private int width, height;  // width and height of window, set in reshape()
	
	private double x = 0, z = 0;   // (x,z) position of the avatar.
	
	private double angle = 0; // angle that the avatar is facing, where the initial
	                            // value of zero means that the avatar is facing in
	                            // in the direction of the negative z-axis.
	
		
	private GLUT glut = new GLUT();  // For drawing the objects.
	private GLU glu = new GLU();     // For gluPerspective()
	
	public Avatar() {
		setPreferredSize(new Dimension(700,500));
		addGLEventListener(this);
		addKeyListener(this);
	}

	/**
	 * This method will be called when the GLJPanel is first
	 * created to set up OpenGL.
	 */
	public void init(GLAutoDrawable drawable) {
		GL2 gl = drawable.getGL().getGL2();
		gl.glClearColor(0,0,0,1);
		gl.glEnable(GL2.GL_LIGHTING);
		gl.glEnable(GL2.GL_LIGHT0);
		gl.glEnable(GL2.GL_COLOR_MATERIAL);
		gl.glEnable(GL2.GL_DEPTH_TEST);
		gl.glEnable(GL2.GL_NORMALIZE);
	}

	/**
	 * Display method renders the current object, using the current texture.
	 */
	public void display(GLAutoDrawable drawable) {
		GL2 gl = drawable.getGL().getGL2();
		gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);

		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(60, (double)width/height, 0.1, 200);
		gl.glMatrixMode(GL2.GL_MODELVIEW);

		// TODO:  Set up the modelview matrix to use the avatar's viewing transform!

		drawWorld(gl);

	}
	
	/**
	 * Arrow keys move the avatar; HOME key restores the original view point.
	 */
	public void keyPressed(KeyEvent e) {
		int key = e.getKeyCode();
		
		// TODO: implement the keys.
		
		repaint();
	}

	/**
	 * Draws the contents of the world.
	 */
	private void drawWorld(GL2 gl) {
		
		// Draw the "ground", consisting of a big green disk (actually a flattened 
		// cylinder).  The top of the cylinder lies in the xz-plane.
		gl.glPushMatrix();
		gl.glColor3f(0, 0.6f, 0.2f);
		gl.glRotatef(90, 1, 0, 0);  // Rotate about the x-axis, since base starts out in the xy-plane.
		glut.glutSolidCylinder(50,1,128,1);
		gl.glPopMatrix();
		
		// Draw some object of various colors standing on the disk
		
		gl.glPushMatrix();
		gl.glColor3f(1, 0.8f, 0.4f);
		gl.glTranslatef(5, 3.5f, -30); // y-translation is to put the base of the teapot in the xz-plane
		glut.glutSolidTeapot(6);
		gl.glPopMatrix();
		
		gl.glPushMatrix();
		gl.glColor3f(0, 0.8f, 1);
		gl.glTranslatef(-5, 0, -15);
		gl.glRotated(-90, 1, 0, 0); // rotate base into the xz-plane
		glut.glutSolidCylinder(2, 5, 32, 12);
		gl.glPopMatrix();
		
		gl.glPushMatrix();
		gl.glColor3f(1,0,0.6f);
		gl.glTranslatef(-15, 0, 25);
		gl.glRotated(-90, 1, 0, 0); // put base in xz-plane
		glut.glutSolidCone(4, 5, 32, 12);
		gl.glPopMatrix();
		
		gl.glPushMatrix();
		gl.glColor3f(1, 0, 0);
		gl.glTranslated(20, 0, 5); // only a hemisphere is "above ground"
		glut.glutSolidSphere(8, 32, 16);
		gl.glPopMatrix();

		gl.glPushMatrix();
		gl.glColor3f(1, 1, 1);
		gl.glTranslatef(-30, 0.2f, 10); // only a hemisphere is "above ground"
		gl.glDisable(GL2.GL_LIGHTING);  // Disable lighting for a better wireframe
		gl.glRotatef(90, 1, 0, 0);
		glut.glutWireSphere(6, 16, 10);
		gl.glEnable(GL2.GL_LIGHTING);
		gl.glPopMatrix();
		
		gl.glPushMatrix();
		gl.glColor3f(0.8f,0.8f,1);
		gl.glTranslatef(30,1.5f,30);
		gl.glRotatef(35,0,1,0);
		glut.glutSolidCube(3);
		gl.glPopMatrix();
				
		// TODO:  Add some more shapes!
	}

	/**
	 * Record the width and height of the window, so they can be used to set
	 * the aspect ratio in gluPerspective(),
	 */
	public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
		this.width = width;
		this.height = height;
	}
	
	// Extra, unused method of the GLEventListener interface
	public void dispose(GLAutoDrawable drawable) { }

	// Extra, unused methods of the KeyListener interface.
	public void keyReleased(KeyEvent e) { }
	public void keyTyped(KeyEvent e) { }
}
