瀏覽代碼

Semi-working animations

- Animations do not look like they do in Blender
- Animated models cannot move
Tankernn 8 年之前
父節點
當前提交
f638d6b18a

+ 4 - 4
src/main/java/eu/tankernn/gameEngine/MainLoop.java

@@ -82,9 +82,9 @@ public class MainLoop {
 		TerrainPack terrainPack = new TerrainPack(loader, texturePack, blendMap, SEED);
 
 		// Player
-		Entity3D entity = new Entity3D(0, new Vector3f(0, 0, 20), new Vector3f(0, 0, 0), 1, loader.getBoundingBox(0));
+		Entity3D entity = new Entity3D(loader.getModel(0), new Vector3f(0, 0, 20), new Vector3f(0, 0, 0), 1, loader.getBoundingBox(0));
 		entities.add(entity);
-		Player player = new Player(0, new Vector3f(10, 0, 50), new Vector3f(0, 0, 0), 1, loader.getBoundingBox(0),
+		Player player = new Player(loader.getModel(0), new Vector3f(10, 0, 50), new Vector3f(0, 0, 0), 1, loader.getBoundingBox(0),
 				terrainPack);
 		entities.add(player);
 		Camera camera = new PlayerCamera(player, terrainPack);
@@ -105,7 +105,7 @@ public class MainLoop {
 		textMaster.loadText(text);
 
 		// Barrel
-		Entity3D barrel = new Entity3D(1, new Vector3f(75, 10, 75), new Vector3f(0, 0, 0), 1f, loader.getBoundingBox(1));
+		Entity3D barrel = new Entity3D(loader.getModel(1), new Vector3f(75, 10, 75), new Vector3f(0, 0, 0), 1f, loader.getBoundingBox(1));
 		entities.add(barrel);
 
 		Light sun = new Light(new Vector3f(100000, 150000, -70000), new Vector3f(1f, 1f, 1f));
@@ -122,7 +122,7 @@ public class MainLoop {
 			float x = rand.nextFloat() * 1000;
 			float z = rand.nextFloat() * 1000;
 
-			entities.add(new Entity3D(2, new Vector3f(x, terrainPack.getTerrainHeightByWorldPos(x, z), z), new Vector3f(),
+			entities.add(new Entity3D(loader.getModel(2), new Vector3f(x, terrainPack.getTerrainHeightByWorldPos(x, z), z), new Vector3f(),
 					1, loader.getBoundingBox(2)));
 		}
 

+ 2 - 0
src/main/java/eu/tankernn/gameEngine/TankernnGame3D.java

@@ -77,6 +77,8 @@ public class TankernnGame3D extends TankernnGame {
 
 	public void update() {
 		super.update();
+		for (Entity3D e : entities)
+			e.update();
 		player.move();
 		picker.update(terrainPack);
 		camera.update();

+ 0 - 1
src/main/java/eu/tankernn/gameEngine/animation/loaders/AnimatedModelLoader.java

@@ -8,7 +8,6 @@ import eu.tankernn.gameEngine.loader.colladaLoader.JointData;
 import eu.tankernn.gameEngine.loader.colladaLoader.JointsData;
 import eu.tankernn.gameEngine.loader.colladaLoader.MeshData;
 import eu.tankernn.gameEngine.loader.textures.ModelTexture;
-import eu.tankernn.gameEngine.loader.textures.Texture;
 import eu.tankernn.gameEngine.renderEngine.Vao;
 import eu.tankernn.gameEngine.util.InternalFile;
 

+ 2 - 1
src/main/java/eu/tankernn/gameEngine/entities/Car.java

@@ -4,6 +4,7 @@ import org.lwjgl.input.Keyboard;
 import org.lwjgl.util.vector.Vector3f;
 
 import eu.tankernn.gameEngine.loader.models.AABB;
+import eu.tankernn.gameEngine.loader.models.TexturedModel;
 import eu.tankernn.gameEngine.renderEngine.DisplayManager;
 import eu.tankernn.gameEngine.settings.Physics;
 import eu.tankernn.gameEngine.terrains.Terrain;
@@ -14,7 +15,7 @@ public class Car extends Player {
 	private static final float MAX_SPEED = 100.0f, ACCELERATION = 20.0f, DECELERATION = 10.0f, BRAKE = 40.0f,
 			TURN_FORCE = 160.0f;
 
-	public Car(int model, Vector3f position, Vector3f rotation, float scale, AABB boundingBox, TerrainPack terrainPack) {
+	public Car(TexturedModel model, Vector3f position, Vector3f rotation, float scale, AABB boundingBox, TerrainPack terrainPack) {
 		super(model, position, rotation, scale, boundingBox, terrainPack);
 	}
 

+ 9 - 6
src/main/java/eu/tankernn/gameEngine/entities/Entity3D.java

@@ -2,17 +2,19 @@ package eu.tankernn.gameEngine.entities;
 
 import org.lwjgl.util.vector.Vector3f;
 
+import eu.tankernn.gameEngine.animation.animatedModel.AnimatedModel;
 import eu.tankernn.gameEngine.loader.models.AABB;
+import eu.tankernn.gameEngine.loader.models.TexturedModel;
 import eu.tankernn.gameEngine.util.IPositionable;
 
 public class Entity3D implements IPositionable {
-	private int model;
+	private TexturedModel model;
 	private Vector3f position;
 	private Vector3f rotation;
 	private float scale;
 	private AABB boundingBox;
 	
-	public Entity3D(int model, Vector3f position, Vector3f rotation, float scale, AABB boundingBox) {
+	public Entity3D(TexturedModel model, Vector3f position, Vector3f rotation, float scale, AABB boundingBox) {
 		this.model = model;
 		this.position = position;
 		this.rotation = rotation;
@@ -25,22 +27,23 @@ public class Entity3D implements IPositionable {
 		this.position.x += dx;
 		this.position.y += dy;
 		this.position.z += dz;
-		updateBoundingBox();
 	}
 	
 	public void increaseRotation(Vector3f deltaRotation) {
 		Vector3f.add(this.rotation, deltaRotation, this.rotation);
 	}
 	
-	private void updateBoundingBox() {
+	public void update() {
 		this.boundingBox.updatePosition(this.position);
+		if (model instanceof AnimatedModel)
+			((AnimatedModel) model).update();
 	}
 	
-	public int getModel() {
+	public TexturedModel getModel() {
 		return model;
 	}
 	
-	public void setModel(int model) {
+	public void setModel(TexturedModel model) {
 		this.model = model;
 	}
 	

+ 2 - 1
src/main/java/eu/tankernn/gameEngine/entities/Player.java

@@ -5,6 +5,7 @@ import org.lwjgl.input.Mouse;
 import org.lwjgl.util.vector.Vector3f;
 
 import eu.tankernn.gameEngine.loader.models.AABB;
+import eu.tankernn.gameEngine.loader.models.TexturedModel;
 import eu.tankernn.gameEngine.renderEngine.DisplayManager;
 import eu.tankernn.gameEngine.settings.Physics;
 import eu.tankernn.gameEngine.terrains.Terrain;
@@ -25,7 +26,7 @@ public class Player extends Entity3D {
 	
 	private float height = 2.0f;
 	
-	public Player(int model, Vector3f position, Vector3f rotation, float scale, AABB boundingBox, TerrainPack terrainPack) {
+	public Player(TexturedModel model, Vector3f position, Vector3f rotation, float scale, AABB boundingBox, TerrainPack terrainPack) {
 		super(model, position, rotation, scale, boundingBox);
 		this.terrainPack = terrainPack;
 	}

+ 58 - 65
src/main/java/eu/tankernn/gameEngine/loader/Loader.java

@@ -21,6 +21,8 @@ import org.lwjgl.opengl.GL20;
 import org.lwjgl.opengl.GL30;
 import org.lwjgl.opengl.GL33;
 
+import eu.tankernn.gameEngine.animation.animatedModel.AnimatedModel;
+import eu.tankernn.gameEngine.animation.loaders.AnimatedModelLoader;
 import eu.tankernn.gameEngine.loader.models.AABB;
 import eu.tankernn.gameEngine.loader.models.TexturedModel;
 import eu.tankernn.gameEngine.loader.obj.ModelData;
@@ -34,7 +36,6 @@ import eu.tankernn.gameEngine.util.InternalFile;
  * General purpose loader
  * 
  * @author Frans
- *
  */
 public class Loader {
 	private List<Integer> vaos = new ArrayList<Integer>();
@@ -43,7 +44,7 @@ public class Loader {
 	private List<Texture> textures = new ArrayList<Texture>();
 	private Map<Integer, TexturedModel> models = new HashMap<Integer, TexturedModel>();
 	private List<AABB> boundingBoxes = new ArrayList<>();
-
+	
 	public Vao loadToVAO(float[] vertices, float[] textureCoords, float[] normals, int[] indices) {
 		Vao model = Vao.create();
 		model.bind();
@@ -55,9 +56,8 @@ public class Loader {
 		rawModels.add(model);
 		return model;
 	}
-
-	public Vao loadToVAO(float[] vertices, float[] textureCoords, float[] normals, float[] tangents,
-			int[] indices) {
+	
+	public Vao loadToVAO(float[] vertices, float[] textureCoords, float[] normals, float[] tangents, int[] indices) {
 		Vao model = Vao.create();
 		model.bind();
 		model.createIndexBuffer(indices);
@@ -69,7 +69,7 @@ public class Loader {
 		rawModels.add(model);
 		return model;
 	}
-
+	
 	public int createEmptyVBO(int floatCount) {
 		int vboID = GL15.glGenBuffers();
 		vbos.add(vboID);
@@ -78,9 +78,8 @@ public class Loader {
 		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
 		return vboID;
 	}
-
-	public void addInstacedAttribute(int vao, int vbo, int attribute, int dataSize, int instancedDataLength,
-			int offset) {
+	
+	public void addInstacedAttribute(int vao, int vbo, int attribute, int dataSize, int instancedDataLength, int offset) {
 		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
 		GL30.glBindVertexArray(vao);
 		GL20.glVertexAttribPointer(attribute, dataSize, GL11.GL_FLOAT, false, instancedDataLength * 4, offset * 4);
@@ -88,7 +87,7 @@ public class Loader {
 		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
 		GL30.glBindVertexArray(0);
 	}
-
+	
 	public void updateVBO(int vboID, float[] data, FloatBuffer buffer) {
 		buffer.clear();
 		buffer.put(data);
@@ -98,7 +97,7 @@ public class Loader {
 		GL15.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, buffer);
 		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
 	}
-
+	
 	public int loadToVAO(float[] positions, float[] textureCoords) {
 		int vaoID = createVAO();
 		storeDataInAttributeList(0, 2, positions);
@@ -106,7 +105,7 @@ public class Loader {
 		unbindVAO();
 		return vaoID;
 	}
-
+	
 	public Vao loadToVAO(float[] positions, int dimensions) {
 		Vao vao = Vao.create();
 		vao.bind();
@@ -114,18 +113,16 @@ public class Loader {
 		vao.unbind();
 		return vao;
 	}
-
+	
 	public Vao loadToVAO(ModelData data) {
-		return (Vao) loadToVAO(data.getVertices(), data.getTextureCoords(), data.getNormals(), data.getTangents(),
-				data.getIndices());
+		return (Vao) loadToVAO(data.getVertices(), data.getTextureCoords(), data.getNormals(), data.getTangents(), 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.
+	 * @param filename The path, relative to the root of the jar file, of the
+	 *        file to load.
 	 * @return The texture ID
 	 * @throws FileNotFoundException
 	 */
@@ -138,26 +135,24 @@ public class Loader {
 	public Texture loadTexture(String filename) throws FileNotFoundException {
 		return loadTexture(new InternalFile(filename));
 	}
-
+	
 	/**
 	 * Creates a new cube map from the images specified. File 0: Right face File
 	 * 1: Left face File 2: Top face File 3: Bottom face File 4: Back face File
 	 * 5: Front face
 	 * 
-	 * @param textureFiles
-	 *            Filenames of images that make up the cube map
+	 * @param textureFiles Filenames of images that make up the cube map
 	 * @return The ID of the new cube map
 	 */
-
+	
 	public Texture loadCubeMap(InternalFile[] textureFiles) {
 		Texture cubeMap = Texture.newCubeMap(textureFiles, 500);
 		textures.add(cubeMap);
 		return cubeMap;
 	}
 	
-	private static final int[] CUBE_INDICES = { 0, 1, 3, 1, 2, 3, 1, 5, 2, 2, 5, 6, 4, 7, 5, 5, 7, 6, 0,
-			3, 4, 4, 3, 7, 7, 3, 6, 6, 3, 2, 4, 5, 0, 0, 5, 1 };
-
+	private static final int[] CUBE_INDICES = {0, 1, 3, 1, 2, 3, 1, 5, 2, 2, 5, 6, 4, 7, 5, 5, 7, 6, 0, 3, 4, 4, 3, 7, 7, 3, 6, 6, 3, 2, 4, 5, 0, 0, 5, 1};
+	
 	public Vao generateCube(float size) {
 		Vao vao = Vao.create();
 		vao.bind();
@@ -167,31 +162,29 @@ public class Loader {
 		rawModels.add(vao);
 		return vao;
 	}
-
+	
 	private static float[] getCubeVertexPositions(float size) {
-		return new float[] { -size, size, size, size, size, size, size, -size, size, -size, -size,
-				size, -size, size, -size, size, size, -size, size, -size, -size, -size, -size,
-				-size };
+		return new float[] {-size, size, size, size, size, size, size, -size, size, -size, -size, size, -size, size, -size, size, size, -size, size, -size, -size, -size, -size, -size};
 	}
-
+	
 	public void cleanUp() {
-		for (int vao : vaos)
+		for (int vao: vaos)
 			GL30.glDeleteVertexArrays(vao);
-		for (int vbo : vbos)
+		for (int vbo: vbos)
 			GL15.glDeleteBuffers(vbo);
-		for (Texture tex : textures)
+		for (Texture tex: textures)
 			tex.delete();
-		for (Vao model : rawModels)
+		for (Vao model: rawModels)
 			model.delete();
 	}
-
+	
 	private int createVAO() {
 		int vaoID = GL30.glGenVertexArrays();
 		vaos.add(vaoID);
 		GL30.glBindVertexArray(vaoID);
 		return vaoID;
 	}
-
+	
 	private void storeDataInAttributeList(int attributeNumber, int coordinateSize, float[] data) {
 		int vboID = GL15.glGenBuffers();
 		vbos.add(vboID);
@@ -201,55 +194,55 @@ public class Loader {
 		GL20.glVertexAttribPointer(attributeNumber, coordinateSize, GL11.GL_FLOAT, false, 0, 0);
 		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
 	}
-
+	
 	private void unbindVAO() {
 		GL30.glBindVertexArray(0);
 	}
-
+	
 	private FloatBuffer storeDataInFloatBuffer(float[] data) {
 		FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
 		buffer.put(data);
 		buffer.flip();
 		return buffer;
 	}
-
+	
 	public Vao loadOBJ(InternalFile objFile) {
 		ModelData data = ObjLoader.loadOBJ(objFile);
 		boundingBoxes.add(new AABB(data));
 		return this.loadToVAO(data);
 	}
-
+	
+	public AnimatedModel loadDAE(InternalFile colladaFile) {
+		return AnimatedModelLoader.loadEntity(colladaFile, new ModelTexture(textures.get(0)));
+	}
+	
 	public void readModelSpecification(InternalFile file) throws IOException {
 		Map<InternalFile, Vao> cachedRawModels = new HashMap<InternalFile, Vao>();
 		Map<InternalFile, Texture> cachedTextures = new HashMap<InternalFile, Texture>();
 		JSONObject spec;
-
+		
 		JSONArray jsonArr = new JSONArray(file.readFile());
-
+		
 		for (int j = 0; j < jsonArr.length(); j++) {
 			spec = jsonArr.getJSONObject(j);
-
+			
 			int id;
 			Vao model;
 			ModelTexture modelTexture;
-
+			
 			id = spec.getInt("id");
-
+			
 			InternalFile objFile = new InternalFile(optFilename(spec, "model", ".obj"));
-
-			String[] textureFiles = {
-					optFilename(spec, "texture", ".png"), 
-					optFilename(spec, "specular", "S.png"),
-					optFilename(spec, "normal", "N.png")
-			};
-
+			
+			String[] textureFiles = {optFilename(spec, "texture", ".png"), optFilename(spec, "specular", "S.png"), optFilename(spec, "normal", "N.png")};
+			
 			if (cachedRawModels.containsKey(objFile))
 				model = cachedRawModels.get(objFile);
 			else {
 				model = loadOBJ(objFile);
 				cachedRawModels.put(objFile, model);
 			}
-
+			
 			Texture[] textures = Arrays.stream(textureFiles).map(fileName -> {
 				try {
 					InternalFile f = new InternalFile(fileName);
@@ -266,31 +259,31 @@ public class Loader {
 					return null;
 				}
 			}).toArray(size -> new Texture[size]);
-
+			
 			modelTexture = new ModelTexture(textures[0]);
 			if (textures[1] != null)
 				modelTexture.setNormalMap(textures[2]);
 			if (textures[2] != null)
 				modelTexture.setSpecularMap(textures[1]);
-
+			
 			modelTexture.setShineDamper(optFloat(spec, "shinedamper", 10.0f));
 			modelTexture.setReflectivity(optFloat(spec, "reflectivity", 0f));
 			modelTexture.setRefractivity(optFloat(spec, "refractivity", 0f));
-
+			
 			modelTexture.setHasTransparency(spec.optBoolean("transparency"));
-
+			
 			models.put(id, new TexturedModel(model, modelTexture));
 		}
 	}
-
+	
 	private float optFloat(JSONObject spec, String key, float defaultValue) {
 		return BigDecimal.valueOf(spec.optDouble(key, (double) defaultValue)).floatValue();
 	}
-
+	
 	private String optFilename(JSONObject spec, String key, String extension) {
 		return spec.has(key) ? spec.getString(key) : spec.get("name") + extension;
 	}
-
+	
 	public int registerModel(int id, TexturedModel model) throws Exception {
 		if (models.containsKey(id)) {
 			throw new Exception("There is already a model registered for the key " + id + ".");
@@ -299,11 +292,11 @@ public class Loader {
 			return id;
 		}
 	}
-
+	
 	public int registerModel(TexturedModel model) throws Exception {
 		if (models.containsValue(model)) {
 			Iterator<Entry<Integer, TexturedModel>> i = models.entrySet().iterator();
-
+			
 			while (i.hasNext()) {
 				Entry<Integer, TexturedModel> e = i.next();
 				if (e.getValue().equals(model)) {
@@ -315,11 +308,11 @@ public class Loader {
 		} else
 			return registerModel(models.size(), model);
 	}
-
+	
 	public TexturedModel getModel(int id) {
 		return models.get(id);
 	}
-
+	
 	public AABB getBoundingBox(int id) {
 		return boundingBoxes.get(id);
 	}

+ 1 - 4
src/main/java/eu/tankernn/gameEngine/renderEngine/MasterRenderer.java

@@ -37,8 +37,6 @@ import eu.tankernn.gameEngine.util.ICamera;
 public class MasterRenderer {
 	private static final Vector4f NO_CLIP = new Vector4f(0, 0, 0, 1);
 	
-	private Loader loader;
-	
 	private EntityRenderer<EntityShader> entityRenderer;
 	private TerrainRenderer terrainRenderer;
 	private SkyboxRenderer skyboxRenderer;
@@ -57,7 +55,6 @@ public class MasterRenderer {
 	 */
 	public MasterRenderer(Loader loader, Camera camera, Skybox skybox) {
 		enableCulling();
-		this.loader = loader;
 		terrainRenderer = new TerrainRenderer(camera.getProjectionMatrix());
 		shadowMapRenderer = new ShadowMapMasterRenderer(camera);
 		skyboxRenderer = new SkyboxRenderer(loader, camera.getProjectionMatrix(), skybox);
@@ -135,7 +132,7 @@ public class MasterRenderer {
 	 *            Entity to add to the list
 	 */
 	public void processEntity(Entity3D entity) {
-		TexturedModel entityModel = loader.getModel(entity.getModel());
+		TexturedModel entityModel = entity.getModel();
 		List<Entity3D> batch = entities.get(entityModel);
 		if (batch != null) {
 			batch.add(entity);

+ 32 - 29
src/main/java/eu/tankernn/gameEngine/renderEngine/entities/EntityRenderer.java

@@ -12,6 +12,8 @@ import org.lwjgl.util.vector.Matrix4f;
 import org.lwjgl.util.vector.Vector3f;
 import org.lwjgl.util.vector.Vector4f;
 
+import eu.tankernn.gameEngine.animation.animatedModel.AnimatedModel;
+import eu.tankernn.gameEngine.animation.renderer.AnimatedModelRenderer;
 import eu.tankernn.gameEngine.entities.Entity3D;
 import eu.tankernn.gameEngine.entities.Light;
 import eu.tankernn.gameEngine.loader.models.TexturedModel;
@@ -25,18 +27,18 @@ import eu.tankernn.gameEngine.util.Maths;
  * Renderer for entities.
  * 
  * @author Frans
- *
  */
 public class EntityRenderer<S extends EntityShader> {
+	private AnimatedModelRenderer animatedRenderer;
+	
 	protected S 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
+	 * @param shader The shader to use when rendering entities
+	 * @param projectionMatrix The projection matrix to use when rendering
+	 *        entities
 	 */
 	@SuppressWarnings("unchecked")
 	public EntityRenderer(Matrix4f projectionMatrix) {
@@ -49,43 +51,45 @@ public class EntityRenderer<S extends EntityShader> {
 		shader.projectionMatrix.loadMatrix(projectionMatrix);
 		shader.connectTextureUnits();
 		shader.stop();
+		animatedRenderer = new AnimatedModelRenderer();
 	}
-
+	
 	/**
 	 * Renders entities to the current frame buffer.
 	 * 
-	 * @param entities
-	 *            The entities to render.
-	 * @param toShadowSpace
-	 *            Transformation matrix to shadow space. Used for applying
-	 *            shadows.
+	 * @param entities The entities to render.
+	 * @param toShadowSpace Transformation matrix to shadow space. Used for
+	 *        applying shadows.
 	 */
-	public void render(Map<TexturedModel, List<Entity3D>> entities, Matrix4f toShadowSpace, ICamera cam,
-			Vector4f clipPlane, List<Light> lights, Texture environmentMap) {
+	public void render(Map<TexturedModel, List<Entity3D>> entities, Matrix4f toShadowSpace, ICamera cam, Vector4f clipPlane, List<Light> lights, Texture environmentMap) {
 		shader.start();
 		shader.plane.loadVec4(clipPlane);
 		shader.skyColor.loadVec3(RED, GREEN, BLUE);
 		shader.loadLights(lights, cam.getViewMatrix());
 		shader.viewMatrix.loadCamera(cam);
-
+		
 		shader.toShadowMapSpace.loadMatrix(toShadowSpace);
 		shader.cameraPosition.loadVec3(cam.getPosition());
-		for (TexturedModel model : entities.keySet()) {
-			prepareTexturedModel(model, environmentMap);
-			List<Entity3D> batch = entities.get(model);
-			for (Entity3D entity : batch) {
-				prepareInstance(entity, model);
-				GL11.glDrawElements(GL11.GL_TRIANGLES, model.getModel().getIndexCount(), GL11.GL_UNSIGNED_INT, 0);
+		for (TexturedModel model: entities.keySet()) {
+			if (model instanceof AnimatedModel)
+				animatedRenderer.render((AnimatedModel) model, cam, lights.get(0).getPosition());
+			else {
+				prepareTexturedModel(model, environmentMap);
+				List<Entity3D> batch = entities.get(model);
+				for (Entity3D entity: batch) {
+					prepareInstance(entity, model);
+					GL11.glDrawElements(GL11.GL_TRIANGLES, model.getModel().getIndexCount(), GL11.GL_UNSIGNED_INT, 0);
+				}
+				unbindTexturedModel(model);
 			}
-			unbindTexturedModel(model);
 		}
 		shader.stop();
 	}
-
+	
 	public void cleanUp() {
 		shader.cleanUp();
 	}
-
+	
 	private void prepareTexturedModel(TexturedModel model, Texture environmentMap) {
 		model.getModel().bind(0, 1, 2, 3);
 		ModelTexture texture = model.getTexture();
@@ -106,20 +110,19 @@ public class EntityRenderer<S extends EntityShader> {
 			texture.getNormalMap().bindToUnit(1);
 		bindEnvironmentMap(environmentMap);
 	}
-
+	
 	private void bindEnvironmentMap(Texture environmentMap) {
 		environmentMap.bindToUnit(10);
 	}
-
+	
 	private void unbindTexturedModel(TexturedModel model) {
 		MasterRenderer.enableCulling();
 		model.getModel().unbind(0, 1, 2, 3);
 	}
-
+	
 	protected void prepareInstance(Entity3D entity, TexturedModel model) {
 		Vector3f rot = entity.getRotation();
-		Matrix4f transformationMatrix = Maths.createTransformationMatrix(entity.getPosition(), rot.x, rot.y, rot.z,
-				entity.getScale());
+		Matrix4f transformationMatrix = Maths.createTransformationMatrix(entity.getPosition(), rot.x, rot.y, rot.z, entity.getScale());
 		shader.transformationMatrix.loadMatrix(transformationMatrix);
 		shader.offset.loadVec2(model.getTextureXOffset(), model.getTextureYOffset());
 	}