浏览代码

Documentation and formatting

Tankernn 9 年之前
父节点
当前提交
215b76285e
共有 27 个文件被更改,包括 632 次插入263 次删除
  1. 1 5
      .classpath
  2. 二进制
      res/sound/bounce.wav
  3. 31 0
      src/main/java/eu/tankernn/gameEngine/TankernnGame.java
  4. 43 0
      src/main/java/eu/tankernn/gameEngine/audio/AudioMaster.java
  5. 37 0
      src/main/java/eu/tankernn/gameEngine/audio/AudioTester.java
  6. 61 0
      src/main/java/eu/tankernn/gameEngine/audio/Source.java
  7. 26 126
      src/main/java/eu/tankernn/gameEngine/entities/Camera.java
  8. 138 0
      src/main/java/eu/tankernn/gameEngine/entities/PlayerCamera.java
  9. 1 1
      src/main/java/eu/tankernn/gameEngine/normalMapping/renderer/NormalMappingRenderer.java
  10. 0 40
      src/main/java/eu/tankernn/gameEngine/particles/InsertionSort.java
  11. 2 1
      src/main/java/eu/tankernn/gameEngine/particles/Particle.java
  12. 2 1
      src/main/java/eu/tankernn/gameEngine/particles/ParticleMaster.java
  13. 26 2
      src/main/java/eu/tankernn/gameEngine/renderEngine/DisplayManager.java
  14. 22 5
      src/main/java/eu/tankernn/gameEngine/renderEngine/EntityRenderer.java
  15. 21 3
      src/main/java/eu/tankernn/gameEngine/renderEngine/Loader.java
  16. 76 17
      src/main/java/eu/tankernn/gameEngine/renderEngine/MasterRenderer.java
  17. 4 2
      src/main/java/eu/tankernn/gameEngine/settings/Settings.java
  18. 3 1
      src/main/java/eu/tankernn/gameEngine/shaders/ShaderProgram.java
  19. 18 0
      src/main/java/eu/tankernn/gameEngine/shaders/StaticShader.java
  20. 6 0
      src/main/java/eu/tankernn/gameEngine/shaders/TerrainShader.java
  21. 9 1
      src/main/java/eu/tankernn/gameEngine/shaders/fragmentShader.glsl
  22. 18 5
      src/main/java/eu/tankernn/gameEngine/shaders/terrainFragmentShader.glsl
  23. 5 1
      src/main/java/eu/tankernn/gameEngine/shaders/vertexShader.glsl
  24. 1 1
      src/main/java/eu/tankernn/gameEngine/shadows/ShadowBox.java
  25. 1 1
      src/main/java/eu/tankernn/gameEngine/shadows/ShadowMapMasterRenderer.java
  26. 9 25
      src/main/java/eu/tankernn/gameEngine/tester/MainLoop.java
  27. 71 25
      src/main/java/eu/tankernn/gameEngine/util/Sorter.java

+ 1 - 5
.classpath

@@ -18,11 +18,7 @@
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="lib" path="lib/PNGDecoder.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>

二进制
res/sound/bounce.wav


+ 31 - 0
src/main/java/eu/tankernn/gameEngine/TankernnGame.java

@@ -0,0 +1,31 @@
+package eu.tankernn.gameEngine;
+
+import eu.tankernn.gameEngine.entities.Camera;
+import eu.tankernn.gameEngine.renderEngine.DisplayManager;
+import eu.tankernn.gameEngine.renderEngine.Loader;
+import eu.tankernn.gameEngine.renderEngine.MasterRenderer;
+
+public class TankernnGame {
+	protected Loader loader;
+	protected MasterRenderer renderer;
+	protected Camera camera;
+	
+	public TankernnGame() {
+		loader = new Loader();
+		camera = new Camera();
+		renderer = new MasterRenderer(loader, camera);
+	}
+	
+	public void update() {
+		camera.update();
+	}
+	
+	public void render() {
+		DisplayManager.updateDisplay();
+	}
+	
+	public void cleanUp() {
+		loader.cleanUp();
+		renderer.cleanUp();
+	}
+}

+ 43 - 0
src/main/java/eu/tankernn/gameEngine/audio/AudioMaster.java

@@ -0,0 +1,43 @@
+package eu.tankernn.gameEngine.audio;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.openal.AL;
+import org.lwjgl.openal.AL10;
+import org.lwjgl.util.WaveData;
+
+public class AudioMaster {
+	
+	private static List<Integer> buffers = new ArrayList<Integer>();
+	
+	public static void init() {
+		try {
+			AL.create();
+		} catch (LWJGLException e) {
+			e.printStackTrace();
+		}
+	}
+	
+	public static void setListenerData(float x, float y, float z) {
+		AL10.alListener3f(AL10.AL_POSITION, x, y, z);
+		AL10.alListener3f(AL10.AL_VELOCITY, 0, 0, 0);
+	}
+	
+	public static int loadSound(String file) {
+		int buffer = AL10.alGenBuffers();
+		buffers.add(buffer);
+		WaveData waveFile = WaveData.create(file);
+		AL10.alBufferData(buffer, waveFile.format, waveFile.data, waveFile.samplerate);
+		waveFile.dispose();
+		return buffer;
+	}
+	
+	public static void cleanUp() {
+		for (int buffer: buffers) {
+			AL10.alDeleteBuffers(buffer);
+		}
+		AL.destroy();
+	}
+}

+ 37 - 0
src/main/java/eu/tankernn/gameEngine/audio/AudioTester.java

@@ -0,0 +1,37 @@
+package eu.tankernn.gameEngine.audio;
+
+import java.io.IOException;
+
+import org.lwjgl.openal.AL10;
+import org.lwjgl.openal.AL11;
+
+public class AudioTester {
+	public static void main(String[] args) throws IOException, InterruptedException {
+		AudioMaster.init();
+		AudioMaster.setListenerData(0, 0, 0);
+		AL10.alDistanceModel(AL10.AL_INVERSE_DISTANCE_CLAMPED);
+		
+		int buffer = AudioMaster.loadSound("sound/bounce.wav");
+		Source source = new Source();
+		source.setLooping(true);
+		source.play(buffer);
+		
+		float xPos = 0;
+		source.setPosition(xPos, 0, 0);
+		
+		char c = ' ';
+		while (c != 'q') {
+			//c = (char) System.in.read();
+			
+			xPos -= 0.03f;
+			source.setPosition(xPos, 0, 0);
+			System.out.println(xPos);
+			Thread.sleep(10);
+			
+		}
+		
+		source.delete();
+		AudioMaster.cleanUp();
+		
+	}
+}

+ 61 - 0
src/main/java/eu/tankernn/gameEngine/audio/Source.java

@@ -0,0 +1,61 @@
+package eu.tankernn.gameEngine.audio;
+
+import org.lwjgl.openal.AL10;
+
+public class Source {
+	private int sourceId;
+	
+	public Source() {
+		sourceId = AL10.alGenSources();
+		AL10.alSourcef(sourceId, AL10.AL_ROLLOFF_FACTOR, 6);
+		AL10.alSourcef(sourceId, AL10.AL_REFERENCE_DISTANCE, 6);
+		AL10.alSourcef(sourceId, AL10.AL_MAX_DISTANCE, 50);
+	}
+	
+	public void play(int buffer) {
+		stop();
+		AL10.alSourcei(sourceId, AL10.AL_BUFFER, buffer);
+		AL10.alSourcePlay(sourceId);
+	}
+	
+	public void delete() {
+		stop();
+		AL10.alDeleteSources(sourceId);
+	}
+	
+	public void pause () {
+		AL10.alSourcePause(sourceId);
+	}
+	
+	public void continuePlaying () {
+		AL10.alSourcePlay(sourceId);
+	}
+	
+	public void stop () {
+		AL10.alSourceStop(sourceId);
+	}
+	
+	public void setVelocity(float x, float y, float z) {
+		AL10.alSource3f(sourceId, AL10.AL_VELOCITY, x, y, z);
+	}
+	
+	public void setLooping(boolean looping) {
+		AL10.alSourcei(sourceId, AL10.AL_LOOPING, looping ? AL10.AL_TRUE : AL10.AL_FALSE);
+	}
+	
+	public boolean isPlaying() {
+		return AL10.alGetSourcei(sourceId, AL10.AL_SOURCE_STATE) == AL10.AL_PLAYING;
+	}
+	
+	public void setVolume(int volume) {
+		AL10.alSourcei(sourceId, AL10.AL_GAIN, volume);
+	}
+	
+	public void setPitch(float pitch) {
+		AL10.alSourcef(sourceId, AL10.AL_PITCH, pitch);
+	}
+	
+	public void setPosition(float x, float y, float z) {
+		AL10.alSource3f(sourceId, AL10.AL_POSITION, x, y, z);
+	}
+}

+ 26 - 126
src/main/java/eu/tankernn/gameEngine/entities/Camera.java

@@ -1,102 +1,32 @@
 package eu.tankernn.gameEngine.entities;
 
-import java.nio.IntBuffer;
-
-import org.lwjgl.LWJGLException;
-import org.lwjgl.input.Cursor;
-import org.lwjgl.input.Keyboard;
-import org.lwjgl.input.Mouse;
 import org.lwjgl.util.vector.Vector3f;
 
-import eu.tankernn.gameEngine.terrains.TerrainPack;
-
+/**
+ * Camera for determining the view frustum when rendering.
+ * 
+ * @author Frans
+ */
 public class Camera implements Positionable {
 	
-	private float distanceFromPlayer = 50;
-	private float angleAroundPlayer = 0;
-	private float lockedPosition = 0;
-	private boolean isLocked = false;
-	
-	private Vector3f position = new Vector3f(0, 10, 0);
-	private float pitch = 20;
-	private float yaw;
-	private float roll;
+	protected Vector3f position = new Vector3f(0, 10, 0);
+	protected float pitch = 20;
+	protected float yaw;
+	protected float roll;
 	
-	private Player player;
-	private TerrainPack terrainPack;
-	
-	public Camera(Player player, TerrainPack terrainPack) {
-		this.player = player;
-		this.terrainPack = terrainPack;
+	public Camera(Vector3f position) {
+		this.position = position;
 	}
 	
-	public void move() {
-		calculateZoom();
-		if (Mouse.isButtonDown(0) || Mouse.isButtonDown(1)) {
-			if (!this.isLocked) {
-				this.isLocked = true;
-				this.lockedPosition = player.getRotY();
-			}
-			try {
-				Mouse.setNativeCursor(new Cursor(1, 1, 0, 0, 1, IntBuffer.allocate(1), null)); //Hide the cursor
-			} catch (LWJGLException e) {
-				e.printStackTrace();
-			}
-			
-			calculatePitch();
-			calculateAngleAroundPlayer();
-			
-			if (Mouse.isButtonDown(1)) {
-				float targetRot = this.angleAroundPlayer + this.lockedPosition;
-				this.lockedPosition = 0;
-				float delta = targetRot - player.getRotY();
-				player.increaseRotation(0, delta, 0);
-			}
-		} else {
-			if (this.isLocked) {
-				this.isLocked = false;
-				this.angleAroundPlayer -= (player.getRotY() - lockedPosition);
-			}
-			try {
-				Mouse.setNativeCursor(null);
-			} catch (LWJGLException e) {
-				e.printStackTrace();
-			}
-		}
-		
-		if (!this.isLocked) {
-			adjustToCenter();
-		}
-		
-		float horizontalDistance = calculateHorizontalDistance();
-		float verticalDistance = calculateVerticalDistance();
-		calculateCameraPosition(horizontalDistance, verticalDistance);
+	public Camera() {
 		
-		if (this.isLocked) {
-			this.yaw = 180 - (lockedPosition + angleAroundPlayer);
-		} else
-			this.yaw = 180 - (player.getRotY() + angleAroundPlayer);
 	}
 	
-	private void adjustToCenter() {
-		if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
-			this.angleAroundPlayer = this.angleAroundPlayer % 360;
-			
-			if (this.angleAroundPlayer < 0)
-				this.angleAroundPlayer = 360 + this.angleAroundPlayer;
-			
-			if (this.angleAroundPlayer -10 < 0) {
-				this.angleAroundPlayer = 0;
-				return;
-			}
-			
-			if (this.angleAroundPlayer < 180)
-				this.angleAroundPlayer -= 10;
-			else
-				this.angleAroundPlayer += 10;
-		}
-	}
-
+	/**
+	 * Points the camera so that that <code>entity</code> is in the center.
+	 * 
+	 * @param entity The <code>Entity</code> to point towards
+	 */
 	public void pointToEntity(Entity entity) {
 		Vector3f targetPos = entity.getPosition();
 		Vector3f delta = new Vector3f();
@@ -109,44 +39,8 @@ public class Camera implements Positionable {
 		
 	}
 	
-	private float calculateHorizontalDistance() {
-		return (float) (distanceFromPlayer * Math.cos(Math.toRadians(pitch)));
-	}
-	
-	private float calculateVerticalDistance() {
-		return (float) (distanceFromPlayer * Math.sin(Math.toRadians(pitch)));
-	}
-	
-	private void calculateCameraPosition(float horizDistance, float verticDistance) {
-		float theta;
-		if (this.isLocked)
-			theta = lockedPosition + angleAroundPlayer;
-		else
-			theta = player.getRotY() + angleAroundPlayer;
-		float offsetX = (float) (horizDistance * Math.sin(Math.toRadians(theta)));
-		float offsetZ = (float) (horizDistance * Math.cos(Math.toRadians(theta)));
-		position.x = player.getPosition().x - offsetX;
-		position.z = player.getPosition().z - offsetZ;
-		position.y = player.getPosition().y + player.getHeight() + verticDistance;
-		position.y = Math.max(position.y, terrainPack.getTerrainHeightByWorldPos(position.x, position.z) + 1);
-	}
-	
-	private void calculateZoom() {
-		float zoomLevel = Mouse.getDWheel() * 0.1f;
-		distanceFromPlayer -= zoomLevel;
-		distanceFromPlayer = Math.max(distanceFromPlayer, 10);
-		distanceFromPlayer = Math.min(distanceFromPlayer, 100);
-	}
-	
-	private void calculatePitch() {
-		float pitchChange = Mouse.getDY() * 0.1f;
-		pitch -= pitchChange;
-		pitch = Math.min(pitch, 90);
-	}
-	
-	private void calculateAngleAroundPlayer() {
-		float angleChange = Mouse.getDX() * 0.3f;
-		angleAroundPlayer -= angleChange;
+	public void update() {
+		
 	}
 	
 	public Vector3f getPosition() {
@@ -164,11 +58,17 @@ public class Camera implements Positionable {
 	public float getRoll() {
 		return roll;
 	}
-
+	
+	/**
+	 * Inverts the pitch of the camera, used for water rendering.
+	 */
 	public void invertPitch() {
 		this.pitch = -pitch;
 	}
 	
+	/**
+	 * Inverts the roll of the camera, used for water rendering.
+	 */
 	public void invertRoll() {
 		this.roll = -roll;
 	}

+ 138 - 0
src/main/java/eu/tankernn/gameEngine/entities/PlayerCamera.java

@@ -0,0 +1,138 @@
+package eu.tankernn.gameEngine.entities;
+
+import java.nio.IntBuffer;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Cursor;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+
+import eu.tankernn.gameEngine.terrains.TerrainPack;
+
+public class PlayerCamera extends Camera {
+	
+	private float distanceFromPlayer = 50;
+	private float angleAroundPlayer = 0;
+	private float lockedPosition = 0;
+	private boolean isLocked = false;
+	
+	private Player player;
+	private TerrainPack terrainPack;
+	
+	
+	public PlayerCamera(Player player, TerrainPack terrainPack) {
+		this.player = player;
+		this.terrainPack = terrainPack;
+	}
+	
+	/**
+	 * Handles player input regarding camera movement.
+	 */
+	@Override
+	public void update() {
+		calculateZoom();
+		if (Mouse.isButtonDown(0) || Mouse.isButtonDown(1)) {
+			if (!this.isLocked) {
+				this.isLocked = true;
+				this.lockedPosition = player.getRotY();
+			}
+			try {
+				Mouse.setNativeCursor(new Cursor(1, 1, 0, 0, 1, IntBuffer.allocate(1), null)); //Hide the cursor
+			} catch (LWJGLException e) {
+				e.printStackTrace();
+			}
+			
+			calculatePitch();
+			calculateAngleAroundPlayer();
+			
+			if (Mouse.isButtonDown(1)) {
+				float targetRot = this.angleAroundPlayer + this.lockedPosition;
+				this.lockedPosition = 0;
+				float delta = targetRot - player.getRotY();
+				player.increaseRotation(0, delta, 0);
+			}
+		} else {
+			if (this.isLocked) {
+				this.isLocked = false;
+				this.angleAroundPlayer -= (player.getRotY() - lockedPosition);
+			}
+			try {
+				Mouse.setNativeCursor(null);
+			} catch (LWJGLException e) {
+				e.printStackTrace();
+			}
+		}
+		
+		if (!this.isLocked) {
+			adjustToCenter();
+		}
+		
+		float horizontalDistance = calculateHorizontalDistance();
+		float verticalDistance = calculateVerticalDistance();
+		calculateCameraPosition(horizontalDistance, verticalDistance);
+		
+		if (this.isLocked) {
+			this.yaw = 180 - (lockedPosition + angleAroundPlayer);
+		} else
+			this.yaw = 180 - (player.getRotY() + angleAroundPlayer);
+	}
+	
+	private void adjustToCenter() {
+		if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
+			this.angleAroundPlayer = this.angleAroundPlayer % 360;
+			
+			if (this.angleAroundPlayer < 0)
+				this.angleAroundPlayer = 360 + this.angleAroundPlayer;
+			
+			if (this.angleAroundPlayer - 10 < 0) {
+				this.angleAroundPlayer = 0;
+				return;
+			}
+			
+			if (this.angleAroundPlayer < 180)
+				this.angleAroundPlayer -= 10;
+			else
+				this.angleAroundPlayer += 10;
+		}
+	}
+	
+	private float calculateHorizontalDistance() {
+		return (float) (distanceFromPlayer * Math.cos(Math.toRadians(pitch)));
+	}
+	
+	private float calculateVerticalDistance() {
+		return (float) (distanceFromPlayer * Math.sin(Math.toRadians(pitch)));
+	}
+	
+	private void calculateCameraPosition(float horizDistance, float verticDistance) {
+		float theta;
+		if (this.isLocked)
+			theta = lockedPosition + angleAroundPlayer;
+		else
+			theta = player.getRotY() + angleAroundPlayer;
+		float offsetX = (float) (horizDistance * Math.sin(Math.toRadians(theta)));
+		float offsetZ = (float) (horizDistance * Math.cos(Math.toRadians(theta)));
+		position.x = player.getPosition().x - offsetX;
+		position.z = player.getPosition().z - offsetZ;
+		position.y = player.getPosition().y + player.getHeight() + verticDistance;
+		position.y = Math.max(position.y, terrainPack.getTerrainHeightByWorldPos(position.x, position.z) + 1);
+	}
+	
+	private void calculateZoom() {
+		float zoomLevel = Mouse.getDWheel() * 0.1f;
+		distanceFromPlayer -= zoomLevel;
+		distanceFromPlayer = Math.max(distanceFromPlayer, 10);
+		distanceFromPlayer = Math.min(distanceFromPlayer, 100);
+	}
+	
+	private void calculatePitch() {
+		float pitchChange = Mouse.getDY() * 0.1f;
+		pitch -= pitchChange;
+		pitch = Math.min(pitch, 90);
+	}
+	
+	private void calculateAngleAroundPlayer() {
+		float angleChange = Mouse.getDX() * 0.3f;
+		angleAroundPlayer -= angleChange;
+	}
+}

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/normalMapping/renderer/NormalMappingRenderer.java

@@ -16,7 +16,7 @@ import eu.tankernn.gameEngine.entities.Light;
 import eu.tankernn.gameEngine.models.RawModel;
 import eu.tankernn.gameEngine.models.TexturedModel;
 import eu.tankernn.gameEngine.renderEngine.MasterRenderer;
-import eu.tankernn.gameEngine.renderEngine.Settings;
+import eu.tankernn.gameEngine.settings.Settings;
 import eu.tankernn.gameEngine.textures.ModelTexture;
 import eu.tankernn.gameEngine.util.Maths;
 

+ 0 - 40
src/main/java/eu/tankernn/gameEngine/particles/InsertionSort.java

@@ -1,40 +0,0 @@
-package eu.tankernn.gameEngine.particles;
-
-import java.util.List;
-
-/**
- * A simple implementation of an insertion sort. I implemented this very quickly
- * the other day so it may not be perfect or the most efficient! Feel free to
- * implement your own sorter instead.
- * 
- * @author Karl
- */
-public class InsertionSort {
-	
-	/**
-	 * Sorts a list of particles so that the particles with the highest distance
-	 * from the camera are first, and the particles with the shortest distance
-	 * are last.
-	 * 
-	 * @param list - the list of particles needing sorting.
-	 */
-	public static void sortHighToLow(List<Particle> list) {
-		for (int i = 1; i < list.size(); i++) {
-			Particle item = list.get(i);
-			if (item.getDistance() > list.get(i - 1).getDistance()) {
-				sortUpHighToLow(list, i);
-			}
-		}
-	}
-	
-	private static void sortUpHighToLow(List<Particle> list, int i) {
-		Particle item = list.get(i);
-		int attemptPos = i - 1;
-		while (attemptPos != 0 && list.get(attemptPos - 1).getDistance() < item.getDistance()) {
-			attemptPos--;
-		}
-		list.remove(i);
-		list.add(attemptPos, item);
-	}
-	
-}

+ 2 - 1
src/main/java/eu/tankernn/gameEngine/particles/Particle.java

@@ -4,11 +4,12 @@ import org.lwjgl.util.vector.Vector2f;
 import org.lwjgl.util.vector.Vector3f;
 
 import eu.tankernn.gameEngine.entities.Camera;
+import eu.tankernn.gameEngine.entities.Positionable;
 import eu.tankernn.gameEngine.renderEngine.DisplayManager;
 import eu.tankernn.gameEngine.settings.Physics;
 
 
-public class Particle {
+public class Particle implements Positionable {
 	private Vector3f position;
 	private Vector3f velocity;
 	private float gravityEffect;

+ 2 - 1
src/main/java/eu/tankernn/gameEngine/particles/ParticleMaster.java

@@ -11,6 +11,7 @@ import org.lwjgl.util.vector.Matrix4f;
 
 import eu.tankernn.gameEngine.entities.Camera;
 import eu.tankernn.gameEngine.renderEngine.Loader;
+import eu.tankernn.gameEngine.util.Sorter;
 
 public class ParticleMaster {
 	private static Map<ParticleTexture, List<Particle>> particles = new HashMap<ParticleTexture, List<Particle>>();
@@ -37,7 +38,7 @@ public class ParticleMaster {
 				}
 			}
 			if (!entry.getKey().usesAdditiveBlending())
-				InsertionSort.sortHighToLow(list);
+				new Sorter<Particle>(list, camera).sortByDistance();
 		}
 	}
 	

+ 26 - 2
src/main/java/eu/tankernn/gameEngine/renderEngine/DisplayManager.java

@@ -6,18 +6,29 @@ import org.lwjgl.Sys;
 import org.lwjgl.opengl.ContextAttribs;
 import org.lwjgl.opengl.Display;
 import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL13;
 import org.lwjgl.opengl.PixelFormat;
 
+import eu.tankernn.gameEngine.settings.Settings;
+
+/**
+ * Handles the OpenGL display.
+ * 
+ * @author Frans
+ */
 public class DisplayManager {
 	
 	private static final int WIDTH = 1600;
 	private static final int HEIGHT = 900;
 	private static final int FPS_CAP = 60;
-	private static final int MULTISAMPLING = 2;
+	private static final int MULTISAMPLING = 8;
 	
 	private static long lastFrameTime;
 	private static float delta;
 	
+	/**
+	 * Creates a new display.
+	 */
 	public static void createDisplay() {
 		ContextAttribs attribs = new ContextAttribs(3, 3)
 				.withForwardCompatible(true)
@@ -25,7 +36,8 @@ public class DisplayManager {
 		
 		try {
 			Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
-			Display.create(new PixelFormat(8, 8, 0, MULTISAMPLING), attribs);
+			Display.create(new PixelFormat().withSamples(MULTISAMPLING).withDepthBits(24), attribs);
+			GL11.glEnable(GL13.GL_MULTISAMPLE);
 		} catch (LWJGLException e) {
 			e.printStackTrace();
 		}
@@ -36,6 +48,9 @@ public class DisplayManager {
 		Display.setTitle(Settings.GAME_NAME);
 	}
 	
+	/**
+	 * Updates the display. Should be called every frame.
+	 */
 	public static void updateDisplay() {
 		Display.sync(FPS_CAP);
 		Display.update();
@@ -44,10 +59,19 @@ public class DisplayManager {
 		lastFrameTime = currentFrameTime;
 	}
 	
+	/**
+	 * Get the current tick length in seconds. Used to synchronize
+	 * time-dependent actions.
+	 * 
+	 * @return Current tick length in seconds
+	 */
 	public static float getFrameTimeSeconds() {
 		return delta;
 	}
 	
+	/**
+	 * Close the display. Call when game stops.
+	 */
 	public static void closeDisplay() {
 		Display.destroy();
 	}

+ 22 - 5
src/main/java/eu/tankernn/gameEngine/renderEngine/EntityRenderer.java

@@ -14,22 +14,39 @@ import eu.tankernn.gameEngine.models.TexturedModel;
 import eu.tankernn.gameEngine.shaders.StaticShader;
 import eu.tankernn.gameEngine.textures.ModelTexture;
 import eu.tankernn.gameEngine.util.Maths;
-
+/**
+ * Renderer for entities.
+ * @author Frans
+ *
+ */
 public class EntityRenderer {
 	private StaticShader shader;
-	
+	/**
+	 * Starts shader and loads initial values.
+	 * @param shader The shader to use when rendering entities
+	 * @param projectionMatrix The projection matrix to use when rendering entities
+	 */
 	public EntityRenderer(StaticShader shader, Matrix4f projectionMatrix) {
 		this.shader = shader;
 		shader.start();
 		shader.loadProjectionMatrix(projectionMatrix);
+		shader.connectTextureUnits();
 		shader.stop();
 	}
 	
-	public void render(Map<TexturedModel,List<Entity>> entities) {
-		for (TexturedModel model : entities.keySet()) {
+	/**
+	 * Renders entities to the current frame buffer.
+	 * 
+	 * @param entities The entities to render.
+	 * @param toShadowSpace Transformation matrix to shadow space. Used for
+	 *        applying shadows.
+	 */
+	public void render(Map<TexturedModel, List<Entity>> entities, Matrix4f toShadowSpace) {
+		shader.loadToShadowSpaceMatrix(toShadowSpace);
+		for (TexturedModel model: entities.keySet()) {
 			prepareTexturedModel(model);
 			List<Entity> batch = entities.get(model);
-			for (Entity entity : batch) {
+			for (Entity entity: batch) {
 				prepareInstance(entity);
 				GL11.glDrawElements(GL11.GL_TRIANGLES, model.getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
 			}

+ 21 - 3
src/main/java/eu/tankernn/gameEngine/renderEngine/Loader.java

@@ -9,6 +9,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.EXTTextureFilterAnisotropic;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL13;
 import org.lwjgl.opengl.GL14;
@@ -16,12 +17,19 @@ import org.lwjgl.opengl.GL15;
 import org.lwjgl.opengl.GL20;
 import org.lwjgl.opengl.GL30;
 import org.lwjgl.opengl.GL33;
+import org.lwjgl.opengl.GLContext;
+
 import de.matthiasmann.twl.utils.PNGDecoder;
 import de.matthiasmann.twl.utils.PNGDecoder.Format;
 import eu.tankernn.gameEngine.models.RawModel;
 import eu.tankernn.gameEngine.objLoader.ModelData;
+import eu.tankernn.gameEngine.settings.Settings;
 import eu.tankernn.gameEngine.textures.TextureData;
-
+/**
+ * General purpose loader
+ * @author Frans
+ *
+ */
 public class Loader {
 	private List<Integer> vaos = new ArrayList<Integer>();
 	private List<Integer> vbos = new ArrayList<Integer>();
@@ -94,12 +102,22 @@ public class Loader {
 	public RawModel loadToVAO(ModelData data) {
 		return loadToVAO(data.getVertices(), data.getTextureCoords(), data.getNormals(), data.getIndices());
 	}
-	
+	/**
+	 * Loads a texture to the GPU.
+	 * @param filename The path, relative to the root of the jar file, of the file to load.
+	 * @return The texture ID
+	 */
 	public int loadTexture(String filename) {
 		int textureID = 0;
 		try {
 			textureID = loadPNGTexture(getClass().getResourceAsStream("/" + filename + ".png"), GL13.GL_TEXTURE0);
-			GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, -2.4f);
+			GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0f);
+			if (GLContext.getCapabilities().GL_EXT_texture_filter_anisotropic) {
+				float amount = Math.min(Settings.ANISOTROPIC_FILTERING_AMOUNT, GL11.glGetFloat(EXTTextureFilterAnisotropic.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT));
+				GL11.glTexParameterf(GL11.GL_TEXTURE_2D, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, amount);
+			} else {
+				System.out.println("Anisotropic filtering not supported.");
+			}
 		} catch (NullPointerException e) {
 			System.err.println("Could not load texture: " + filename);
 			e.printStackTrace();

+ 76 - 17
src/main/java/eu/tankernn/gameEngine/renderEngine/MasterRenderer.java

@@ -1,11 +1,11 @@
 package eu.tankernn.gameEngine.renderEngine;
 
-import static eu.tankernn.gameEngine.renderEngine.Settings.BLUE;
-import static eu.tankernn.gameEngine.renderEngine.Settings.FAR_PLANE;
-import static eu.tankernn.gameEngine.renderEngine.Settings.FOV;
-import static eu.tankernn.gameEngine.renderEngine.Settings.GREEN;
-import static eu.tankernn.gameEngine.renderEngine.Settings.NEAR_PLANE;
-import static eu.tankernn.gameEngine.renderEngine.Settings.RED;
+import static eu.tankernn.gameEngine.settings.Settings.BLUE;
+import static eu.tankernn.gameEngine.settings.Settings.FAR_PLANE;
+import static eu.tankernn.gameEngine.settings.Settings.FOV;
+import static eu.tankernn.gameEngine.settings.Settings.GREEN;
+import static eu.tankernn.gameEngine.settings.Settings.NEAR_PLANE;
+import static eu.tankernn.gameEngine.settings.Settings.RED;
 import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
 import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
 
@@ -31,6 +31,11 @@ import eu.tankernn.gameEngine.shadows.ShadowMapMasterRenderer;
 import eu.tankernn.gameEngine.skybox.SkyboxRenderer;
 import eu.tankernn.gameEngine.terrains.Terrain;
 
+/**
+ * Handles most of the rendering in the game.
+ * 
+ * @author Frans
+ */
 public class MasterRenderer {
 	private StaticShader staticShader = new StaticShader();
 	private TerrainShader terrainShader = new TerrainShader();
@@ -43,12 +48,16 @@ public class MasterRenderer {
 	
 	private Matrix4f projectionMatrix;
 	
-	private Map<TexturedModel,List<Entity>> entities = new HashMap<TexturedModel, List<Entity>>();
-	private Map<TexturedModel,List<Entity>> normalMapEntities = new HashMap<TexturedModel, List<Entity>>();
+	private Map<TexturedModel, List<Entity>> entities = new HashMap<TexturedModel, List<Entity>>();
+	private Map<TexturedModel, List<Entity>> normalMapEntities = new HashMap<TexturedModel, List<Entity>>();
 	private List<Terrain> terrains = new ArrayList<Terrain>();
 	
-	
-	
+	/**
+	 * Sets up most other renderers for rendering.
+	 * 
+	 * @param loader The main <code>Loader</code>, used by some other renderers
+	 * @param camera The main <code>Camera</code>
+	 */
 	public MasterRenderer(Loader loader, Camera camera) {
 		enableCulling();
 		createProjectionMatrix();
@@ -59,26 +68,46 @@ public class MasterRenderer {
 		shadowMapRenderer = new ShadowMapMasterRenderer(camera);
 	}
 	
+	/**
+	 * Enables culling of faces facing away from the camera.
+	 */
 	public static void enableCulling() {
 		GL11.glEnable(GL11.GL_CULL_FACE);
 		GL11.glCullFace(GL11.GL_BACK);
 	}
 	
+	/**
+	 * Disables culling of faces facing away from the camera. Used when
+	 * rendering flat objects.
+	 */
 	public static void disableCulling() {
 		GL11.glDisable(GL11.GL_CULL_FACE);
 	}
 	
+	/**
+	 * Renders a scene.
+	 * 
+	 * @param scene The <code>Scene</code> to render.
+	 * @param clipPlane The clip plane.
+	 */
 	public void renderScene(Scene scene, Vector4f clipPlane) {
 		scene.getTerrainPack().prepareRenderTerrains(this);
-		for (Entity e : scene.getEntities()) {
+		for (Entity e: scene.getEntities()) {
 			processEntity(e);
 		}
-		for (Entity e : scene.getNormalEntities()) {
+		for (Entity e: scene.getNormalEntities()) {
 			processNormalMappedEntity(e);
 		}
 		render(scene.getLights(), scene.getCamera(), clipPlane);
 	}
 	
+	/**
+	 * Renders the current scene to the current buffer.
+	 * 
+	 * @param lights List of lights in the scene.
+	 * @param camera The main camera.
+	 * @param clipPlane The clip plane.
+	 */
 	public void render(List<Light> lights, Camera camera, Vector4f clipPlane) {
 		prepare();
 		staticShader.start();
@@ -86,7 +115,7 @@ public class MasterRenderer {
 		staticShader.loadSkyColor(RED, GREEN, BLUE);
 		staticShader.loadLights(lights);
 		staticShader.loadViewMatrix(camera);
-		entityRenderer.render(entities);
+		entityRenderer.render(entities, shadowMapRenderer.getToShadowMapSpaceMatrix());
 		staticShader.stop();
 		
 		normalMapRenderer.render(normalMapEntities, clipPlane, lights, camera);
@@ -94,6 +123,7 @@ public class MasterRenderer {
 		terrainShader.start();
 		terrainShader.loadClipPlane(clipPlane);
 		terrainShader.loadSkyColor(RED, GREEN, BLUE);
+		terrainShader.loadShadowMapSize(ShadowMapMasterRenderer.SHADOW_MAP_SIZE);
 		terrainShader.loadLights(lights);
 		terrainShader.loadViewMatrix(camera);
 		terrainRenderer.render(terrains, shadowMapRenderer.getToShadowMapSpaceMatrix());
@@ -106,10 +136,15 @@ public class MasterRenderer {
 		normalMapEntities.clear();
 	}
 	
+	/**
+	 * Adds an entity to the list of entities.
+	 * 
+	 * @param entity Entity to add to the list
+	 */
 	public void processEntity(Entity entity) {
 		TexturedModel entityModel = entity.getModel();
 		List<Entity> batch = entities.get(entityModel);
-		if (batch!=null) {
+		if (batch != null) {
 			batch.add(entity);
 		} else {
 			List<Entity> newBatch = new ArrayList<Entity>();
@@ -118,10 +153,15 @@ public class MasterRenderer {
 		}
 	}
 	
+	/**
+	 * Same as {@link #processEntity(Entity)}, but for normal-mapped entities.
+	 * 
+	 * @param entity Entity to add to the list
+	 */
 	public void processNormalMappedEntity(Entity entity) {
 		TexturedModel entityModel = entity.getModel();
 		List<Entity> batch = normalMapEntities.get(entityModel);
-		if (batch!=null) {
+		if (batch != null) {
 			batch.add(entity);
 		} else {
 			List<Entity> newBatch = new ArrayList<Entity>();
@@ -130,22 +170,35 @@ public class MasterRenderer {
 		}
 	}
 	
+	/**
+	 * Adds specified terrain to the terrain list.
+	 * 
+	 * @param terrain Terrain object to add to list
+	 */
 	public void processTerrain(Terrain terrain) {
 		terrains.add(terrain);
 	}
 	
 	public void renderShadowMap(List<Entity> entityList, Light sun) {
-		for (Entity e : entityList) {
+		for (Entity e: entityList) {
 			processEntity(e);
 		}
 		shadowMapRenderer.render(entities, sun);
 		entities.clear();
 	}
 	
+	/**
+	 * Gets the shadow map texture from the <code>shadowMapRenderer</code>.
+	 * 
+	 * @return
+	 */
 	public int getShadowMapTexture() {
 		return shadowMapRenderer.getShadowMap();
 	}
 	
+	/**
+	 * Runs the cleanup method for the other renderers.
+	 */
 	public void cleanUp() {
 		staticShader.cleanUp();
 		terrainShader.cleanUp();
@@ -153,6 +206,9 @@ public class MasterRenderer {
 		shadowMapRenderer.cleanUp();
 	}
 	
+	/**
+	 * Prepares the current buffer for rendering.
+	 */
 	public void prepare() {
 		GL11.glEnable(GL11.GL_DEPTH_TEST | GL11.GL_DEPTH_BUFFER_BIT);
 		GL11.glClearColor(RED, GREEN, BLUE, 1);
@@ -175,7 +231,10 @@ public class MasterRenderer {
 		projectionMatrix.m32 = -((2 * FAR_PLANE * NEAR_PLANE) / frustum_length);
 		projectionMatrix.m33 = 0;
 	}
-
+	/**
+	 * Gets the current projection matrix.
+	 * @return The current projection matrix
+	 */
 	public Matrix4f getProjectionMatrix() {
 		return projectionMatrix;
 	}

+ 4 - 2
src/main/java/eu/tankernn/gameEngine/renderEngine/Settings.java → src/main/java/eu/tankernn/gameEngine/settings/Settings.java

@@ -1,8 +1,8 @@
-package eu.tankernn.gameEngine.renderEngine;
+package eu.tankernn.gameEngine.settings;
 
 public class Settings {
 	public static final boolean DEBUG = true;
-	public static final String GAME_NAME = "Tankernn game";
+	public static final String GAME_NAME = "Tankernn game engine tester";
 	
 	//Display settings
 	public static final float FOV = 70;
@@ -13,4 +13,6 @@ public class Settings {
 	public static final float RED = 0.7f;
 	public static final float GREEN = 0.75f;
 	public static final float BLUE = 0.8f;
+	
+	public static final float ANISOTROPIC_FILTERING_AMOUNT = 4f;
 }

+ 3 - 1
src/main/java/eu/tankernn/gameEngine/shaders/ShaderProgram.java

@@ -2,6 +2,7 @@ package eu.tankernn.gameEngine.shaders;
 
 import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.nio.FloatBuffer;
 
@@ -98,7 +99,8 @@ public abstract class ShaderProgram {
 		StringBuilder shaderSource = new StringBuilder();
 		
 		try {
-			BufferedReader reader = new BufferedReader(new InputStreamReader(ShaderProgram.class.getResourceAsStream(file))); //new FileReader(new File(URLDecoder.decode(ShaderProgram.class.getResource(file).getPath(), "UTF-8"))));
+			InputStream in = ShaderProgram.class.getResourceAsStream(file);
+			BufferedReader reader = new BufferedReader(new InputStreamReader(in));
 			String line;
 			while ((line = reader.readLine()) != null) {
 				shaderSource.append(line).append('\n');

+ 18 - 0
src/main/java/eu/tankernn/gameEngine/shaders/StaticShader.java

@@ -31,6 +31,9 @@ public class StaticShader extends ShaderProgram {
 	private int location_numberOfRows;
 	private int location_offset;
 	private int location_plane;
+	private int location_toShadowMapSpace;
+	private int location_shadowMap;
+	private int location_shadowDistance;
 	
 	public StaticShader() {
 		super(VERTEX_FILE, FRAGMENT_FILE);
@@ -55,6 +58,9 @@ public class StaticShader extends ShaderProgram {
 		location_numberOfRows = super.getUniformLocation("numberOfRows");
 		location_offset = super.getUniformLocation("offset");
 		location_plane = super.getUniformLocation("plane");
+		location_toShadowMapSpace = super.getUniformLocation("toShadowMapSpace");
+		location_shadowMap = super.getUniformLocation("shadowMap");
+		location_shadowDistance = super.getUniformLocation("shadowDistance");
 		
 		location_lightPosition = new int[MAX_LIGHTS];
 		location_lightColor = new int[MAX_LIGHTS];
@@ -66,6 +72,18 @@ public class StaticShader extends ShaderProgram {
 		}
 	}
 	
+	public void connectTextureUnits() {
+		super.loadInt(location_shadowMap, 5);
+	}
+	
+	public void loadShadowDistance(float distance) {
+		super.loadFloat(location_shadowDistance, distance);
+	}
+	
+	public void loadToShadowSpaceMatrix(Matrix4f matrix) {
+		super.loadMatrix(location_toShadowMapSpace, matrix);
+	}
+	
 	public void loadClipPlane(Vector4f plane) {
 		super.loadVector(location_plane, plane);
 	}

+ 6 - 0
src/main/java/eu/tankernn/gameEngine/shaders/TerrainShader.java

@@ -35,6 +35,7 @@ public class TerrainShader extends ShaderProgram {
 	private int location_toShadowMapSpace;
 	private int location_shadowMap;
 	private int location_shadowDistance;
+	private int location_shadowMapSize;
 	
 	public TerrainShader() {
 		super(VERTEX_FILE, FRAGMENT_FILE);
@@ -64,6 +65,7 @@ public class TerrainShader extends ShaderProgram {
 		location_toShadowMapSpace = super.getUniformLocation("toShadowMapSpace");
 		location_shadowMap = super.getUniformLocation("shadowMap");
 		location_shadowDistance = super.getUniformLocation("shadowDistance");
+		location_shadowMapSize = super.getUniformLocation("shadowMapSize");
 		
 		location_lightPosition = new int[MAX_LIGHTS];
 		location_lightColor = new int[MAX_LIGHTS];
@@ -84,6 +86,10 @@ public class TerrainShader extends ShaderProgram {
 		super.loadInt(location_shadowMap, 5);
 	}
 	
+	public void loadShadowMapSize(float size) {
+		super.loadFloat(location_shadowMapSize, size);
+	}
+	
 	public void loadShadowDistance(float distance) {
 		super.loadFloat(location_shadowDistance, distance);
 	}

+ 9 - 1
src/main/java/eu/tankernn/gameEngine/shaders/fragmentShader.glsl

@@ -5,9 +5,11 @@ in vec3 surfaceNormal;
 in vec3 toLightVector[4]; //4 max light sources
 in vec3 toCameraVector;
 in float visibility;
+in vec4 shadowCoords;
 
 out vec4 out_Color;
 
+uniform sampler2D shadowMap;
 uniform sampler2D textureSampler;
 uniform vec3 lightColor[4]; //4 max light sources
 uniform vec3 attenuation[4];
@@ -19,6 +21,12 @@ uniform vec3 skyColor;
 
 void main(void){
 	
+	float objectNearestLight = texture(shadowMap, shadowCoords.xy).r;
+	float lightFactor = 1.0;
+	if (shadowCoords.z > objectNearestLight + 0.002) {
+		lightFactor = 1.0 - 0.4;
+	}
+	
 	vec3 unitNormal = normalize(surfaceNormal);
 	vec3 unitVectorToCamera = normalize(toCameraVector);
 	
@@ -44,7 +52,7 @@ void main(void){
 		totalSpecular = totalSpecular + (dampedFactor * reflectivity * lightColor[i])/attFactor;
 	}
 	
-	totalDiffuse = max(totalDiffuse, 0.2); //Ambient lighting 2.0
+	totalDiffuse = max(totalDiffuse * lightFactor, 0.2); //Ambient lighting 2.0
 	
 	vec4 textureColor = texture(textureSampler, pass_textureCoords);
 	if (textureColor.a < 0.5) {

+ 18 - 5
src/main/java/eu/tankernn/gameEngine/shaders/terrainFragmentShader.glsl

@@ -15,6 +15,7 @@ uniform sampler2D gTexture;
 uniform sampler2D bTexture;
 uniform sampler2D blendMap;
 uniform sampler2D shadowMap;
+uniform float shadowMapSize;
 
 uniform vec3 lightColor[4]; //4 max light sources
 uniform vec3 attenuation[4];
@@ -22,14 +23,26 @@ uniform float shineDamper;
 uniform float reflectivity;
 uniform vec3 skyColor;
 
+const int pcfCount = 2;
+const float totalTexels = (pcfCount * 2.0 + 1.0) * (pcfCount * 2.0 + 1.0);
+
 void main(void) {
 	
-	float objectNearestLight = texture(shadowMap, shadowCoords.xy).r;
-	float lightFactor = 1.0;
-	if (shadowCoords.z > objectNearestLight) {
-		lightFactor = 1.0 - (shadowCoords.w * 0.4);
+	float texelSize = 1.0 / shadowMapSize;
+	float total = 0.0;
+	
+	for (int x = -pcfCount; x <= pcfCount; x++) {
+		for (int y = -pcfCount; y <= pcfCount; y++) {
+			float objectNearestLight = texture(shadowMap, shadowCoords.xy + vec2(x, y) * texelSize).r;
+			if (shadowCoords.z > objectNearestLight) {
+				total += 1.0;
+			}
+		}
 	}
 	
+	total /= totalTexels;
+	float lightFactor = 1.0 - (total * shadowCoords.w);
+	
 	vec3 unitNormal = normalize(surfaceNormal);
 	vec3 unitVectorToCamera = normalize(toCameraVector);
 	
@@ -64,7 +77,7 @@ void main(void) {
 		totalSpecular = totalSpecular + (dampedFactor * reflectivity * lightColor[i])/attFactor;
 	}
 	
-	totalDiffuse = max(totalDiffuse, 0.2) * lightFactor; //Ambient lighting 2.0
+	totalDiffuse = max(totalDiffuse * lightFactor, 0.2); //Ambient lighting 2.0
 	
 	out_Color = vec4(totalDiffuse, 1.0) * totalColor + vec4(totalSpecular, 1.0);
 	out_Color = mix(vec4(skyColor, 1.0), out_Color, visibility);

+ 5 - 1
src/main/java/eu/tankernn/gameEngine/shaders/vertexShader.glsl

@@ -9,6 +9,7 @@ out vec3 surfaceNormal;
 out vec3 toLightVector[4]; //4 max light sources
 out vec3 toCameraVector;
 out float visibility;
+out vec4 shadowCoords;
 
 uniform mat4 transformationMatrix;
 uniform mat4 projectionMatrix;
@@ -20,6 +21,9 @@ uniform float useFakeLighting;
 uniform float numberOfRows;
 uniform vec2 offset;
 
+uniform mat4 toShadowMapSpace;
+uniform float shadowDistance;
+
 const float density = 0.004;
 const float gradient = 2.0;
 
@@ -27,7 +31,7 @@ uniform vec4 plane;
 
 void main(void) {
 	vec4 worldPosition = transformationMatrix * vec4(position, 1.0);
-	
+	shadowCoords = toShadowMapSpace * worldPosition;
 	gl_ClipDistance[0] = dot(worldPosition, plane);
 	
 	vec4 positionRelativeToCam = viewMatrix * worldPosition;

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/shadows/ShadowBox.java

@@ -6,7 +6,7 @@ import org.lwjgl.util.vector.Vector3f;
 import org.lwjgl.util.vector.Vector4f;
 
 import eu.tankernn.gameEngine.entities.Camera;
-import eu.tankernn.gameEngine.renderEngine.Settings;
+import eu.tankernn.gameEngine.settings.Settings;
 
 /**
  * Represents the 3D cuboidal area of the world in which objects will cast

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/shadows/ShadowMapMasterRenderer.java

@@ -24,7 +24,7 @@ import eu.tankernn.gameEngine.models.TexturedModel;
  */
 public class ShadowMapMasterRenderer {
 
-	private static final int SHADOW_MAP_SIZE = 4096;
+	public static final int SHADOW_MAP_SIZE = 4096;
 
 	private ShadowFrameBuffer shadowFbo;
 	private ShadowShader shader;

+ 9 - 25
src/main/java/eu/tankernn/gameEngine/tester/MainLoop.java

@@ -1,17 +1,11 @@
 package eu.tankernn.gameEngine.tester;
 
 import java.io.File;
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
 
-import org.lwjgl.LWJGLException;
-import org.lwjgl.openal.AL;
-import org.lwjgl.openal.AL10;
 import org.lwjgl.opengl.Display;
-import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL30;
 import org.lwjgl.util.vector.Vector2f;
 import org.lwjgl.util.vector.Vector3f;
 import org.lwjgl.util.vector.Vector4f;
@@ -20,6 +14,7 @@ import eu.tankernn.gameEngine.entities.Camera;
 import eu.tankernn.gameEngine.entities.Entity;
 import eu.tankernn.gameEngine.entities.Light;
 import eu.tankernn.gameEngine.entities.Player;
+import eu.tankernn.gameEngine.entities.PlayerCamera;
 import eu.tankernn.gameEngine.font.meshCreator.FontType;
 import eu.tankernn.gameEngine.font.meshCreator.GUIText;
 import eu.tankernn.gameEngine.font.rendering.TextMaster;
@@ -44,10 +39,7 @@ import eu.tankernn.gameEngine.textures.TerrainTexture;
 import eu.tankernn.gameEngine.textures.TerrainTexturePack;
 import eu.tankernn.gameEngine.util.MousePicker;
 import eu.tankernn.gameEngine.util.Sorter;
-import eu.tankernn.gameEngine.water.WaterFrameBuffers;
 import eu.tankernn.gameEngine.water.WaterMaster;
-import eu.tankernn.gameEngine.water.WaterRenderer;
-import eu.tankernn.gameEngine.water.WaterShader;
 import eu.tankernn.gameEngine.water.WaterTile;
 
 public class MainLoop {
@@ -55,25 +47,13 @@ public class MainLoop {
 	private static final int SEED = 1235;
 	
 	public static void main(String[] args) {
+		System.setProperty("org.lwjgl.librarypath", new File("natives").getAbsolutePath());
 		List<Entity> entities = new ArrayList<Entity>();
 		List<Entity> normalMapEntities = new ArrayList<Entity>();
 		TerrainPack terrainPack = new TerrainPack();
 		
 		DisplayManager.createDisplay();
 		Loader loader = new Loader();
-		System.setProperty("org.lwjgl.librarypath", new File("natives").getAbsolutePath());
-		
-//		try {
-//			AL.create();
-//		} catch (LWJGLException e) {
-//			e.printStackTrace();
-//		}
-//		int source = AL10.alGenSources();
-//		int buffer = AL10.alGenBuffers();
-//		AL10.alBufferData(buffer, AL10.AL_FORMAT_STEREO16, ByteBuffer.allocate(100), 10);
-//		AL10.alSource3f(source, AL10.AL_POSITION, 1, 1, 1);
-//		AL10.alSourceQueueBuffers(source, buffer);
-//		AL10.alSourcePlay(source);
 		
 		// Monkey
 		ModelData monkeyData = OBJFileLoader.loadOBJ("character");
@@ -89,7 +69,7 @@ public class MainLoop {
 		TexturedModel monkey = new TexturedModel(monkeyModel, new ModelTexture(loader.loadTexture("white")));
 		Player player = new Player(monkey, new Vector3f(10, 0, 50), 0, 0, 0, 1, terrainPack);
 		entities.add(player);
-		Camera camera = new Camera(player, terrainPack);
+		Camera camera = new PlayerCamera(player, terrainPack);
 		
 		MasterRenderer renderer = new MasterRenderer(loader, camera);
 		ParticleMaster.init(loader, renderer.getProjectionMatrix());
@@ -112,6 +92,10 @@ public class MainLoop {
 		List<Light> lights = new ArrayList<Light>();
 		lights.add(sun);
 		lights.add(flashLight);
+		lights.add(new Light(new Vector3f(10, 100,0), new Vector3f(0,1,0)));
+		lights.add(new Light(new Vector3f(20, 100,0), new Vector3f(0,0,1)));
+		lights.add(new Light(new Vector3f(30, 100,0), new Vector3f(1,0,0)));
+		lights.add(new Light(new Vector3f(40, 100,0), new Vector3f(1,1,0)));
 		
 		// ### Terrain textures ###
 		
@@ -166,7 +150,7 @@ public class MainLoop {
 		while (!Display.isCloseRequested()) {
 			barrel.increaseRotation(0, 1, 0);
 			player.move(terrainPack);
-			camera.move();
+			camera.update();
 			picker.update();
 			
 			if (picker.getCurrentTerrainPoint() != null) {
@@ -187,7 +171,7 @@ public class MainLoop {
 			}
 			
 			//Sort list of lights
-			lights = Sorter.sortByDistance(camera, lights);
+			lights = new Sorter<Light>(lights, camera).sortByDistance();
 			
 			renderer.renderShadowMap(entities, sun);
 			

+ 71 - 25
src/main/java/eu/tankernn/gameEngine/util/Sorter.java

@@ -1,33 +1,79 @@
 package eu.tankernn.gameEngine.util;
 
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
-
 import eu.tankernn.gameEngine.entities.Positionable;
 
-public class Sorter {
-	public static <T extends Positionable> List<T> sortByDistance(Positionable centerPoint, List<T> objects) {
-		if (objects.size() < 2)
-			return objects;
-		
-		Map<T, Float> lengths = new HashMap<T, Float>();
-		for (T pos : objects)
-			lengths.put(pos, Maths.distanceBetweenPoints(centerPoint.getPosition(), pos.getPosition()));
-		
-		List<T> sortedList = new ArrayList<T>();
-		sortedList.addAll(objects);
+public class Sorter <T extends Positionable> {
+	private List<T> list;
+	private Positionable centerPoint;
+	
+	public Sorter (List<T> list, Positionable centerPoint) {
+		this.centerPoint = centerPoint;
+		this.list = list;
+	}
+	
+	public List<T> sortByDistance() {
+		quickSort(0, list.size() -1);
+		return list;
 		
-		for (int j = 1; j < sortedList.size(); j++) {
-			for (int i = j; i < sortedList.size(); i++) {
-				if (lengths.get(sortedList.get(i)) < lengths.get(sortedList.get(i - 1))) {
-					T temp = sortedList.get(i);
-					sortedList.set(i, sortedList.get(i - 1));
-					sortedList.set(i - 1, temp);
-				}
-			}
-		}
-		return sortedList;
+//		if (objects.size() < 2)
+//			return objects;
+//		
+//		Map<T, Float> lengths = new HashMap<T, Float>();
+//		for (T pos: objects)
+//			lengths.put(pos, Maths.distanceBetweenPoints(centerPoint.getPosition(), pos.getPosition()));
+//		
+//		List<T> sortedList = new ArrayList<T>();
+//		sortedList.addAll(objects);
+//		
+//		for (int j = 1; j < sortedList.size(); j++) {
+//			for (int i = j; i < sortedList.size(); i++) {
+//				if (lengths.get(sortedList.get(i)) < lengths.get(sortedList.get(i - 1))) {
+//					T temp = sortedList.get(i);
+//					sortedList.set(i, sortedList.get(i - 1));
+//					sortedList.set(i - 1, temp);
+//				}
+//			}
+//		}
+//		return sortedList;
+	}
+	
+	private void quickSort(int lowIndex, int highIndex) {
+        int i = lowIndex;
+        int j = highIndex;
+        // calculate pivot number, I am taking pivot as middle index number
+        float pivot = Maths.distanceBetweenPoints(list.get(lowIndex+(highIndex-lowIndex)/2).getPosition(), centerPoint.getPosition());
+        // Divide into two arrays
+        while (i <= j) {
+            /**
+             * In each iteration, we will identify a number from left side which
+             * is greater then the pivot value, and also we will identify a number
+             * from right side which is less then the pivot value. Once the search
+             * is done, then we exchange both numbers.
+             */
+            while (Maths.distanceBetweenPoints(list.get(i).getPosition(), centerPoint.getPosition()) < pivot) {
+                i++;
+            }
+            while (Maths.distanceBetweenPoints(list.get(j).getPosition(), centerPoint.getPosition()) > pivot) {
+                j--;
+            }
+            if (i <= j) {
+                swap(i, j);
+                //move index to next position on both sides
+                i++;
+                j--;
+            }
+        }
+        // call quickSort() method recursively
+        if (lowIndex < j)
+            quickSort(lowIndex, j);
+        if (i < highIndex)
+            quickSort(i, highIndex);
+	}
+	
+	private void swap(int i, int j) {
+		T temp = list.get(i);
+		list.set(i, list.get(j));
+		list.set(j, temp);
 	}
 }