content: /*
   * Copyright (C) 2010-2014 - Andreas Maier 
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
  */
  package edu.stanford.rsl.apps.gui.opengl;
  
  
  import java.awt.Color;
  import java.awt.Dimension;
  import java.awt.event.WindowAdapter;
  import java.awt.event.WindowEvent;
  
  import javax.media.opengl.GL;
  import javax.media.opengl.GL4bc;
  import javax.media.opengl.GLAutoDrawable;
  import javax.media.opengl.GLEventListener;
  import javax.media.opengl.awt.GLJPanel;
  import javax.swing.JFrame;
  
  import com.jogamp.opengl.util.Animator;
  
  import edu.stanford.rsl.conrad.cuda.MouseControlable;
  import edu.stanford.rsl.conrad.geometry.AbstractShape;
  import edu.stanford.rsl.conrad.geometry.shapes.compound.CompoundShape;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.Edge;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.Triangle;
  
  
  
  public abstract class OpenGLViewer extends JFrame implements GLEventListener, MouseControlable {
  	private static final long serialVersionUID = 5230114485975361359L;
  	protected float rotationX;
  	protected float rotationY;
  	protected float translationX;
  	protected float translationY;
  	protected float translationZ =0;
  	protected boolean initialized;
  	private int width = 300;
  	private int height = 300;
  	private static Animator animator;
  	protected GLJPanel panel;
  
  	public OpenGLViewer (String title){
  		super(title);
  		panel = new GLJPanel();
  		panel.addGLEventListener(this);
  		panel.setPreferredSize(new Dimension(width, height));
  		edu.stanford.rsl.conrad.cuda.MouseControl mouseControl = new edu.stanford.rsl.conrad.cuda.MouseControl(this);
  		panel.addMouseMotionListener(mouseControl);
  		panel.addMouseWheelListener(mouseControl);
  		this.add(panel);
  		pack();
  		setVisible(true);
  		boolean animate = true;
  		if (animate) {
  			animator = new Animator(panel);
  			animator.setRunAsFastAsPossible(true);
  			animator.start();
  		}
  
  		addWindowListener(new WindowAdapter()
  		{
  			public void windowClosing(WindowEvent e)
  			{
  				runExit();
  			}
  		});
  	}
  
  	/**
  	 * Implementation of GLEventListener: Called then the GLAutoDrawable was
  	 * reshaped
  	 */
  	public void reshape(
  			GLAutoDrawable drawable, int x, int y, int width, int height)
  	{
  		this.width = width;
  		this.height = height;
  
  	}
  
  	/**
  	 * Draws a Cube at the position location
  	 * @param gl the gldrawable
  	 * @param location the loaction
  	 * @param scale the scale of the cube
  	 */
  	public void drawCube(GL4bc gl, PointND location, double scale, double colorR, double colorG, double colorB){
  		gl.glPushMatrix();
  		gl.glTranslated(location.get(0), location.get(1), location.get(2));
  		gl.glScaled(scale, scale, scale);
  
  		OpenGLViewer.makeCube(gl, colorR, colorG, colorB);
  		gl.glPopMatrix();		
  	}
  	
  	public static void drawTriangleShape(GL4bc gl, AbstractShape shape){
  		if (shape instanceof Triangle) {
  			OpenGLViewer.drawTriangle(gl, (Triangle) shape);
  		}
  		if (shape instanceof CompoundShape) {
  			CompoundShape cs = (CompoundShape) shape;
  			for (AbstractShape s: cs){
  				drawTriangleShape(gl, s);
  			}
  		}
  	}
  
  	public static void drawTriangle(GL4bc gl, Triangle triangle){
  		Color color = new Color(0.9f, 0.5f, 0.2f);
  		drawTriangle(gl, triangle, color);
  	}
  	
  	public static void drawTriangle(GL4bc gl, Triangle triangle, Color color){
  		PointND point = triangle.getA(); 
  		gl.glColor3f(color.getRed(), color.getGreen(), color.getBlue());
  		
  		
  		gl.glCullFace(GL.GL_BACK);
  		gl.glBegin(GL.GL_TRIANGLE_FAN);
  		point = triangle.getA(); 
  		gl.glVertex3f((float)point.get(0), (float)point.get(1), (float)point.get(2));
  		point = triangle.getB(); 
  		gl.glVertex3f((float)point.get(0), (float)point.get(1), (float)point.get(2));
  		point = triangle.getC(); 
  		gl.glVertex3f((float)point.get(0), (float)point.get(1), (float)point.get(2));
  		gl.glEnd();
  	}
  	
  	public static void drawLine(GL4bc gl, Edge edge){
  		Color color = new Color(0.9f, 0.5f, 0.2f);
  		gl.glColor3f(color.getRed(), color.getGreen(), color.getBlue());
  		
  //		gl.glCullFace(GL.GL_FRONT_AND_BACK);
  		gl.glBegin(GL4bc.GL_LINE_STRIP);
  		
  		PointND point = edge.getPoint();
  		gl.glVertex3f((float)point.get(0), (float)point.get(1), (float)point.get(2));
  		point = edge.getEnd(); 
  		gl.glVertex3f((float)point.get(0), (float)point.get(1), (float)point.get(2));
  		gl.glEnd();
  	}
  
  	/**
  	 * Stops the animator and calls System.exit() in a new Thread.
  	 * (System.exit() may not be called synchronously inside one 
  	 * of the JOGL callbacks)
  	 */
  	protected void runExit()
  	{
  		new Thread(new Runnable()
  		{
  			public void run()
  			{
  				animator.stop();
  				System.exit(0);
  			}
  		}).start();
  	}
  
  	public void updateRotationX(double increment) {
  		rotationX += increment;
  	}
  
  	public void updateRotationY(double increment) {
  		rotationY += increment;
  	}
  
  	public void updateTranslationX(double increment) {
  		translationX += increment;
  	}
  
  	public void updateTranslationY(double increment) {
  		translationY += increment;
  	}
  
  	public void updateTranslationZ(double increment) {
  		translationZ += increment;
  	}
  
  	public static void makeCube(GL4bc gl, double colorR, double colorG, double colorB){
  		//gl.glNewList(2, GL.GL_COMPILE);
  		gl.glColor3d(colorR, colorG, colorB);
  		// Draw the sides of the cube
  		gl.glCullFace(GL.GL_FRONT_AND_BACK);
  		gl.glBegin(GL4bc.GL_QUAD_STRIP);
  		gl.glVertex3d(3, 3, -3);
  		gl.glVertex3d(3, -3, -3);
  		gl.glVertex3d(-3, 3, -3);
  		gl.glVertex3d(-3, -3, -3);
  		gl.glVertex3d(-3, 3, 3);
  		gl.glVertex3d(-3, -3, 3);
  		gl.glVertex3d(3, 3, 3);
  		gl.glVertex3d(3, -3, 3);
  		gl.glVertex3d(3, 3, -3);
  		gl.glVertex3d(3, -3, -3);
  		gl.glEnd();
  		// Draw the top and bottom of the cube
  		gl.glBegin(GL4bc.GL_QUADS);
  		gl.glVertex3d(-3, -3, -3);
  		gl.glVertex3d(3, -3, -3);
  		gl.glVertex3d(3, -3, 3);
  		gl.glVertex3d(-3, -3, 3);
  		gl.glVertex3d(-3, 3, -3);
  		gl.glVertex3d(3, 3, -3);
  		gl.glVertex3d(3, 3, 3);
  		gl.glVertex3d(-3, 3, 3);
  		gl.glEnd();
  		//gl.glEndList();
  	}
  
  }
  