import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;



public class Robots implements GLEventListener {



	public static void main(String[]args){

		GLProfile glp = GLProfile.getDefault(); //Default-Profil verwenden
		GLCapabilities caps = new GLCapabilities(glp);
		GLCanvas canvas = new GLCanvas(caps);
		canvas.addGLEventListener(new Robots());


		JFrame frame = new JFrame("Robots");
		frame.setSize(500, 500);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(canvas);
		frame.setVisible(true);
		frame.pack();

	}


	@Override
	public void init(GLAutoDrawable drawable) {

		GL2 gl = drawable.getGL().getGL2();

		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);//Black background
		gl.glMatrixMode(GL2.GL_PROJECTION); //select the projection matrix
		gl.glLoadIdentity(); //reset the projection matrix
		gl.glOrtho(-5, 5, -5, 5, 0, 100);//orthographic projection

	}

	@Override
	public void display(GLAutoDrawable drawable) {

		GL2 gl = drawable.getGL().getGL2();
		GLU glu = new GLU();

		gl.glClear(GL.GL_COLOR_BUFFER_BIT);

		gl.glMatrixMode(GL2.GL_MODELVIEW);
		gl.glLoadIdentity();//reset modelview matrix
		glu.gluLookAt(4, 6, 16, 0, 0, 0, 0, 1, 0); //position camera

		gl.glColor3d(0.3, 0.3, 0.3); //draw in grey
		for(int i=-5; i<=5;i++){
			gl.glBegin(GL2.GL_LINES); // draw grid
			gl.glVertex3i(i, 0, -5);
			gl.glVertex3i(i, 0,5);	
			gl.glEnd();

			gl.glBegin(GL2.GL_LINES); // draw grid
			gl.glVertex3i(-5, 0, i);
			gl.glVertex3i(5, 0,i);	
			gl.glEnd();

		}

		gl.glBegin(GL2.GL_LINES); // draw x, y and z axis
		gl.glColor3d(1, 0, 0);	
		gl.glVertex3i(0, 0, 0);
		gl.glVertex3i(1, 0, 0);

		gl.glColor3d(0, 1, 0);
		gl.glVertex3i(0, 0, 0);
		gl.glVertex3i(0, 1, 0);

		gl.glColor3d(0, 0, 1);
		gl.glVertex3i(0, 0, 0);
		gl.glVertex3i(0, 0, 1);
		gl.glEnd();

		//now place some robots

		gl.glPushMatrix();
		gl.glTranslated(2, 0, -3);//Translation
		gl.glRotated(45,0,1,0);//Rotation
		gl.glColor3d(1, 1, 1);//Color
		drawRobot(gl,0, -30);//drawRobot
		gl.glPopMatrix();

		//another one
		gl.glPushMatrix();
		gl.glTranslated(2, 0, 3);
		gl.glRotated(30, 0, 1, 0);
		gl.glColor3d(1, 0, 1);
		drawRobot(gl,-25,0);
		gl.glPopMatrix();

		//and a third one
		gl.glPushMatrix();
		gl.glTranslated(-2, 0, -2);
		gl.glRotated(-33, 0, 1, 0);
		gl.glColor3d(0, 1, 1);
		drawRobot(gl,-35,10);
		gl.glPopMatrix();


	}

	@Override
	public void dispose(GLAutoDrawable arg0) {
		// TODO Auto-generated method stub	
	}

	@Override
	public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {
		GL2 gl = drawable.getGL().getGL2();
		//keep aspect ratio 
		gl.glViewport(Math.max(0,(w-h)/2), Math.max(0,(h-w)/2), Math.min(w,h), Math.min(w,h));
	}

	public void drawRobot(GL2 gl, double leftArmRotation, double rightArmRotation){

		gl.glMatrixMode(GL2.GL_MODELVIEW); // work on the modelview matrix

		gl.glPushMatrix();
		gl.glTranslated(0.2, 0, 0); //position right leg
		drawLeg(gl);
		gl.glPopMatrix();

		gl.glPushMatrix();
		gl.glTranslated(0.5, 0, 0); //position left leg
		drawLeg(gl);
		gl.glPopMatrix();

		gl.glPushMatrix();
		gl.glTranslated(0.2, 2, 0); //position upper body		

		gl.glPushMatrix();
		gl.glTranslated(-0.2, 0, 0);//position right arm
		gl.glTranslated(0, 1.5, -0.25);//translate back from rotation point
		gl.glRotated(rightArmRotation, 1, 0, 0);//rotate right arm
		gl.glTranslated(0, -1.5, 0.25);//translate in order to rotate around suitable point
		drawArm(gl);
		gl.glPopMatrix();

		gl.glPushMatrix();				
		gl.glTranslated(0.5, 0, 0);//position left arm
		gl.glTranslated(0, 1.5, -0.25);
		gl.glRotated(leftArmRotation, 1, 0, 0);
		gl.glTranslated(0, -1.5, 0.25);
		drawArm(gl);
		gl.glPopMatrix();

		drawBody(gl);//draw body
		gl.glPopMatrix();

		gl.glPushMatrix();
		gl.glTranslated(0.3, 3.5, -0.1);//position head
		drawHead(gl);
		gl.glPopMatrix();

	}

	//method for drawing a box wireframe
	public void drawBox(GL2 gl, double width, double height, double depth){
		gl.glBegin(GL2.GL_LINE_LOOP);
		gl.glVertex3d(0, 0, 0);
		gl.glVertex3d(width, 0, 0);
		gl.glVertex3d(width, height, 0);
		gl.glVertex3d(0, height, 0);
		gl.glEnd();

		gl.glBegin(GL2.GL_LINE_LOOP);
		gl.glVertex3d(0, 0, -depth);
		gl.glVertex3d(width, 0, -depth);
		gl.glVertex3d(width, height, -depth);
		gl.glVertex3d(0, height, -depth);
		gl.glEnd();

		gl.glBegin(GL2.GL_LINES);
		gl.glVertex3d(0, 0, 0);
		gl.glVertex3d(0, 0, -depth);

		gl.glVertex3d(width, 0, 0);
		gl.glVertex3d(width, 0, -depth);

		gl.glVertex3d(width, height, 0);
		gl.glVertex3d(width, height, -depth);

		gl.glVertex3d(0, height, 0);
		gl.glVertex3d(0, height, -depth);
		gl.glEnd();
	}

	//methods for drawing the body parts
	public void drawArm(GL2 gl){
		drawBox(gl, 0.2, 1.5, 0.5);
	}

	public void drawBody(GL2 gl){
		drawBox(gl, 0.5, 1.5, 0.5);
	}

	public void drawLeg(GL2 gl){
		drawBox(gl, 0.2, 2, 0.5);
	}

	public void drawHead(GL2 gl){
		drawBox(gl, 0.3, 0.5, 0.3);
	}


}
