import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.nio.FloatBuffer;
import javax.swing.*;
import javax.media.opengl.*;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;


import com.jogamp.opengl.util.Animator;




public class Animation extends JFrame{

	GLCanvas canvas;
	SceneView sv;

	public Animation() {

		sv = new SceneView(); //GLEventListener-Objekt

		GLProfile glp = GLProfile.getDefault();
		GLCapabilities caps = new GLCapabilities(glp);
		canvas = new GLCanvas(caps);

		canvas.addGLEventListener(sv);

		add(canvas);

		final Animator animator = new Animator(canvas);
		animator.add(canvas);
		animator.start();

		JFrame frame = new JFrame("Particles");
		frame.setSize(800, 800);
		frame.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e){
				new Thread(){
					public void run(){
						animator.stop();
						System.exit(0);
					}
				}.start();
			}
		});

		setTitle("Animation");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(500,500);
		setVisible(true);

	}



	class SceneView implements GLEventListener {

		float rotPyramid = 0.0f;
		float rotCube = 0.0f;

		public void init(GLAutoDrawable drawable) {
			GL2 gl = drawable.getGL().getGL2();

			gl.glClearColor(1f, 1f, 1f, 0f); // grey background


			gl.glEnable(GL2.GL_LIGHTING);
			gl.glEnable(GL2.GL_LIGHT0);
			gl.glEnable(GL2.GL_NORMALIZE);
			gl.glEnable(GL.GL_DEPTH_TEST);
			gl.glClearDepth(1.0f);
			gl.glDepthFunc(GL.GL_LEQUAL);



		}

		public void display(GLAutoDrawable drawable) {

			update();

			GL2 gl = drawable.getGL().getGL2();
			gl.glClear(GL2.GL_COLOR_BUFFER_BIT|GL2.GL_DEPTH_BUFFER_BIT); //clear background
			GLU glu = new GLU();
			gl.glMatrixMode(GL2.GL_MODELVIEW);
			gl.glLoadIdentity();
			glu.gluLookAt(0, 0, 15, 0, 0, -2, 0, 1, 0);

			//light setup
			float light_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
			float light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
			float light_position[] = { 2.0f, 2.0f, 2.0f, 1.0f };

			gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT, FloatBuffer.wrap(light_ambient));
			gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_DIFFUSE, FloatBuffer.wrap(light_diffuse));
			gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION,FloatBuffer.wrap(light_position));

			//materials

			float mat_ambient[] = { 0.1f, 0.2f, 0.1f, 1.0f };
			float mat_diffuse_pyramid[] = { 0.8f, 0.5f, 0.3f, 1.0f };
			float mat_diffuse_cube[] = { 0.1f, 0.6f, 0.6f, 1.0f };


			gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT, FloatBuffer.wrap(mat_ambient));
			gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_DIFFUSE, FloatBuffer.wrap(mat_diffuse_cube));


			gl.glPushMatrix();
			gl.glRotated(rotCube,0.0,1.0,0.0);
			gl.glTranslated(6, -1, 1);
			drawBox(gl, 2, 2, 2);
			gl.glPopMatrix();

			gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_DIFFUSE, FloatBuffer.wrap(mat_diffuse_pyramid));

			gl.glPushMatrix();
			gl.glRotated(-rotPyramid,0.0,1.0,0.0);
			gl.glTranslated(-1, -1, 1);
			drawPyramid(gl,2.0f,2.0f);
			gl.glPopMatrix();


		}

		public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {
			GL2 gl = drawable.getGL().getGL2();
			GLU glu = new GLU();

			gl.glMatrixMode(GL2.GL_PROJECTION);
			gl.glLoadIdentity();
			glu.gluPerspective(45, w/h, 0.1, 1000);
		}

		public void dispose(GLAutoDrawable drawable) {
		}

		public void drawBox(GL2 gl, double width, double height, double depth){
			gl.glNormal3d(0,0,1);
			gl.glBegin(GL2.GL_QUADS);
			gl.glVertex3d(0, 0, 0);
			gl.glVertex3d(width, 0, 0);
			gl.glVertex3d(width, height, 0);
			gl.glVertex3d(0, height, 0);
			gl.glEnd();

			gl.glNormal3d(0,0,-1);
			gl.glBegin(GL2.GL_QUADS);
			gl.glVertex3d(0, 0, -depth);
			gl.glVertex3d(width, 0, -depth);
			gl.glVertex3d(width, height, -depth);
			gl.glVertex3d(0, height, -depth);
			gl.glEnd();

			gl.glNormal3d(0,-1,0);
			gl.glBegin(GL2.GL_QUADS);
			gl.glVertex3d(0, 0, 0);
			gl.glVertex3d(0, 0, -depth);
			gl.glVertex3d(width, 0, -depth);
			gl.glVertex3d(width, 0, 0);
			gl.glEnd();

			gl.glNormal3d(0,1,0);
			gl.glBegin(GL2.GL_QUADS);
			gl.glVertex3d(0, height, 0);
			gl.glVertex3d(0, height, -depth);
			gl.glVertex3d(width, height, -depth);
			gl.glVertex3d(width, height, 0);
			gl.glEnd();

			gl.glNormal3d(-1,0,0);
			gl.glBegin(GL2.GL_QUADS);
			gl.glVertex3d(0, 0, 0);
			gl.glVertex3d(0, height, 0);
			gl.glVertex3d(0, height, -depth);
			gl.glVertex3d(0, 0, -depth);
			gl.glEnd();

			gl.glNormal3d(1,0,0);
			gl.glBegin(GL2.GL_QUADS);
			gl.glVertex3d(width, 0, 0);
			gl.glVertex3d(width, height, 0);
			gl.glVertex3d(width, height, -depth);
			gl.glVertex3d(width, 0, -depth);
			gl.glEnd();
		}

		public void drawPyramid(GL2 gl, float side, float height){

			gl.glNormal3d(0,-1,0);
			gl.glBegin(GL2.GL_QUADS);
			gl.glVertex3d(0, 0, 0);
			gl.glVertex3d(0, 0, -side);
			gl.glVertex3d(side, 0, -side);
			gl.glVertex3d(side, 0, 0);
			gl.glEnd();


			gl.glBegin(GL2.GL_TRIANGLES);

			float[] a = new float[3];
			float[] b = new float[3];


			a[0] = 0;
			a[1] = -height;
			a[2] = side/2;

			b[0] = side;
			b[1] = -height;
			b[2] = side/2;
			gl.glNormal3fv(crossProduct(a,b));		
			gl.glVertex3d(side/2, height, -side/2);
			gl.glVertex3d(0, 0, 0);
			gl.glVertex3d(side, 0, 0);


			a[0] = side;
			a[1] = -height;
			a[2] = side/2;

			b[0] = side;
			b[1] = -height;
			b[2] = -side+(side/2);
			gl.glNormal3fv(crossProduct(a,b));
			gl.glVertex3d(side/2, height, -side/2);
			gl.glVertex3d(side, 0, 0);
			gl.glVertex3d(side, 0,-side);

			a[0] = side;
			a[1] = -height;
			a[2] = -side-(side/2);

			b[0] = 0;
			b[1] = -height;
			b[2] = -side+(side/2);
			gl.glNormal3fv(crossProduct(a,b));
			gl.glVertex3d(side/2, height, -side/2);
			gl.glVertex3d(side, 0,-side);
			gl.glVertex3d(0, 0,-side);


			a[0] = 0;
			a[1] = -height;
			a[2] = -side+(side/2);

			b[0] = 0;
			b[1] = -height;
			b[2] = side/2;
			gl.glNormal3fv(crossProduct(a,b));
			gl.glVertex3d(side/2, height, -side/2);
			gl.glVertex3d(0, 0,-side);
			gl.glVertex3d(0, 0, 0);

			gl.glEnd();
		}

		private FloatBuffer crossProduct(float[]a, float[]b){

			float[] result = new float[3];

			result[0] = a[1]*b[2] - a[2]*b[1];
			result[1] = a[2]*b[0] - a[0]*b[2];
			result[2] = a[0]*b[1] - a[1]*b[0];

			return FloatBuffer.wrap(result);
		}

		private void update(){
			rotPyramid += 0.5;
			rotCube +=0.5;
		}

	}



	public static void main(String args[]) {
		new Animation();
	}




}