package object;

import java.awt.image.BufferedImage;

import javax.media.opengl.GL;

import devUtil.Vector3;

public class ImageHeightMap {
	
	protected double[][] map;
	
	protected double highestPoint;
	protected double lowestPoint;
	
	public ImageHeightMap(BufferedImage heightMap) {
		
		map = new double[heightMap.getWidth()][heightMap.getHeight()];
		
		highestPoint = Double.MIN_VALUE;
		lowestPoint = Double.MAX_VALUE;
		
		double scale = (double) 1 / (double) 0xFFFFFF;
		
		for(int x = 0; x < map.length; x++)
			for(int y = 0; y < map[x].length; y++) {
				
				map[x][y] = (heightMap.getRGB(x, y) * scale);
				
				if(map[x][y] > highestPoint)
					highestPoint = map[x][y];
				
				if(map[x][y] < lowestPoint)
					lowestPoint = map[x][y];
			}
	}
	
	public double[][] getMapData() {
		return map;
	}
	
	public double getValueAt(int x, int y) {
		return map[x][y];
	}
	
	public double getHighestPoint() {
		return highestPoint;
	}
	
	public double getLowestPoint() {
		return lowestPoint;
	}
	
	public void render(GL gl, double width, double length, double height) {
		
		width /= map.length;
		length /= map[0].length;
		height /= highestPoint - lowestPoint;
		
		gl.glBegin(GL.GL_QUADS);
		
		for(int x = 0; x < map.length - 2; x++)
			for(int z = 0; z < map[x].length - 2; z++) {
				
				setColor(gl, x, z);
				setNormals(gl, x, z);
				
				gl.glVertex3d(x * width, map[x][z] * height, z * length);
				gl.glVertex3d(x * width, map[x][z + 1] * height, (z + 1) * length);
				gl.glVertex3d((x + 1) * width, map[x + 1][z + 1] * height, (z + 1) * length);
				gl.glVertex3d((x + 1) * width, map[x + 1][z] * height, z * length);
			}
		
		gl.glEnd();
	}
	
	protected void setColor(GL gl, int x, int z) {
		
		double height = (map[x][z] + map[x + 1][z] + map[x][z + 1] + map[x + 1][z + 1]) / 4;
		
		gl.glColor3f(
				(float) ((height - lowestPoint) * (1 / (highestPoint - lowestPoint))),
				(float) ((height - lowestPoint) * (1 / (highestPoint - lowestPoint))),
				(float) ((height - lowestPoint) * (1 / (highestPoint - lowestPoint)))
				);
	}
	
	protected void setNormals(GL gl, int x, int y) {
		
		Vector3 horizontal = new Vector3(1, map[x + 1][y] - map[x][y], 1);
		Vector3 vertical = new Vector3(1, map[x][y + 1] - map[x][y], 1);
		
		Vector3 crossProduct = horizontal.crossProduct(vertical);
		
		gl.glNormal3f(
				(float) crossProduct.getX(),
				(float) crossProduct.getY(),
				(float) crossProduct.getZ()
				);
	}
}