package simogl.geometry;

import java.util.Iterator;
import javax.media.opengl.GL;

import simogl.collision.BoundingBox;


/**
 * This class represents a mesh. The mesh uses the display list technology.
 * @author Frank Bruns
 *
 */
public class MeshDL extends AbstractMesh
{
	private int id = 0;
	
	/**
	 * Creates a new mesh object
	 * @param gl
	 */
	public MeshDL(GL gl)
	{
		this.id = gl.glGenLists(1);		
	}
	
	/**
	 * Returns the unique id for this mesh
	 * @return unique mesh id
	 */
	public int getMeshID()
	{
		return this.id;
	}
	
	/**
	 * Sets the unique mesh id
	 * @param id unique mesh id
	 */
	public void setMeshID(int id)
	{
		this.id = id;
	}
	
	/**
	 * This method creates the display list for the mesh object.
	 * It is essentiell to call this method after every face has been
	 * added to mesh object.
	 * @param gl
	 */
	public void createDisplayList(GL gl)	
	{		
		Iterator<Face> iter = this.faces.listIterator();
		
		gl.glNewList(this.id, GL.GL_COMPILE);											
			while(iter.hasNext())
			{
				Face face = iter.next();	
				// first triangle
				gl.glBegin(GL.GL_TRIANGLES);																		
					gl.glNormal3fv(face.getTriangle1().getNormal().getPoint(),0);
					gl.glTexCoord2f(face.getTriangle1().getTexCoordVertex1().getS(), face.getTriangle1().getTexCoordVertex1().getT());					
					gl.glVertex3fv(face.getTriangle1().getVertex1().getPoint(),0);
					
					gl.glNormal3fv(face.getTriangle1().getNormal().getPoint(),0);
					gl.glTexCoord2f(face.getTriangle1().getTexCoordVertex2().getS(), face.getTriangle1().getTexCoordVertex2().getT());
					gl.glVertex3fv(face.getTriangle1().getVertex2().getPoint(),0);
					
					gl.glNormal3fv(face.getTriangle1().getNormal().getPoint(),0);
					gl.glTexCoord2f(face.getTriangle1().getTexCoordVertex3().getS(), face.getTriangle1().getTexCoordVertex3().getT());
					gl.glVertex3fv(face.getTriangle1().getVertex3().getPoint(),0);
				gl.glEnd();
				
				
				// second triangle
				gl.glBegin(GL.GL_TRIANGLES);
					gl.glNormal3fv(face.getTriangle2().getNormal().getPoint(),0);
					gl.glTexCoord2f(face.getTriangle2().getTexCoordVertex1().getS(), face.getTriangle2().getTexCoordVertex1().getT());					
					gl.glVertex3fv(face.getTriangle2().getVertex1().getPoint(),0);
					
					gl.glNormal3fv(face.getTriangle2().getNormal().getPoint(),0);
					gl.glTexCoord2f(face.getTriangle2().getTexCoordVertex2().getS(), face.getTriangle2().getTexCoordVertex2().getT());
					gl.glVertex3fv(face.getTriangle2().getVertex2().getPoint(),0);
					
					gl.glNormal3fv(face.getTriangle2().getNormal().getPoint(),0);
					gl.glTexCoord2f(face.getTriangle2().getTexCoordVertex3().getS(), face.getTriangle2().getTexCoordVertex3().getT());
					gl.glVertex3fv(face.getTriangle2().getVertex3().getPoint(),0);
				gl.glEnd();
			}			
		gl.glEndList();
		
		// create bounding box for the mesh
		this.boundingBox = new BoundingBox(this);
	}
	
	/**
	 * Call this method to draw the mesh
	 * @param gl
	 */
	@Override
	public void draw(GL gl)
	{
		this.enableRenderOptions(gl);		
		this.specializedDraw(gl);		
		this.disableRenderOptions(gl);

	}
	
	/**
	 * Helper method to extract the specialised things just fitting to
	 * drawing of display list. This method is also used by shadow drawing.
	 * @param gl
	 */
	@Override
	public void specializedDraw(GL gl)
	{
		gl.glPushMatrix();				
			this.performTransformations(gl);
			gl.glCallList(this.id);
		gl.glPopMatrix();	
	}
	
	/**
	 * Deletes the mesh
	 * @param gl
	 */
	@Override
	public void deleteMesh(GL gl)
	{
		gl.glDeleteLists(this.id, 1);
	}
}
