Browse Source

Floating-in-world textures

Tankernn 8 years ago
parent
commit
8c68b65f7f
19 changed files with 202 additions and 51 deletions
  1. 0 1
      TODO.txt
  2. 5 0
      src/main/java/eu/tankernn/gameEngine/TankernnGame3D.java
  3. 1 1
      src/main/java/eu/tankernn/gameEngine/entities/Car.java
  4. 5 5
      src/main/java/eu/tankernn/gameEngine/entities/Entity3D.java
  5. 5 1
      src/main/java/eu/tankernn/gameEngine/entities/Player.java
  6. 1 1
      src/main/java/eu/tankernn/gameEngine/entities/projectiles/Projectile.java
  7. 2 8
      src/main/java/eu/tankernn/gameEngine/particles/ParticleRenderer.java
  8. 1 3
      src/main/java/eu/tankernn/gameEngine/renderEngine/entities/EntityRenderer.java
  9. 40 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/gui/floating/FloatingTexture.java
  10. 60 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/gui/floating/FloatingTextureRenderer.java
  11. 18 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/gui/floating/FloatingTextureShader.java
  12. 13 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/gui/floating/floatingFragment.glsl
  13. 13 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/gui/floating/floatingVertex.glsl
  14. 1 3
      src/main/java/eu/tankernn/gameEngine/renderEngine/shadows/ShadowMapEntityRenderer.java
  15. 1 1
      src/main/java/eu/tankernn/gameEngine/renderEngine/terrain/TerrainRenderer.java
  16. 2 2
      src/main/java/eu/tankernn/gameEngine/renderEngine/water/WaterMaster.java
  17. 10 12
      src/main/java/eu/tankernn/gameEngine/renderEngine/water/WaterRenderer.java
  18. 2 2
      src/main/java/eu/tankernn/gameEngine/renderEngine/water/WaterTile.java
  19. 22 11
      src/main/java/eu/tankernn/gameEngine/util/Maths.java

+ 0 - 1
TODO.txt

@@ -1,4 +1,3 @@
-Floating-in-world text
 Texture atlases with the new model spec system.
 Multiplayer
 Modular GUIs

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

@@ -21,6 +21,8 @@ import eu.tankernn.gameEngine.renderEngine.Fbo;
 import eu.tankernn.gameEngine.renderEngine.MasterRenderer;
 import eu.tankernn.gameEngine.renderEngine.MultisampleMultitargetFbo;
 import eu.tankernn.gameEngine.renderEngine.Scene;
+import eu.tankernn.gameEngine.renderEngine.gui.floating.FloatingTexture;
+import eu.tankernn.gameEngine.renderEngine.gui.floating.FloatingTextureRenderer;
 import eu.tankernn.gameEngine.renderEngine.skybox.Skybox;
 import eu.tankernn.gameEngine.renderEngine.water.WaterMaster;
 import eu.tankernn.gameEngine.terrains.TerrainPack;
@@ -32,6 +34,7 @@ public class TankernnGame3D extends TankernnGame {
 	protected MasterRenderer renderer;
 	protected WaterMaster waterMaster;
 	protected ParticleMaster particleMaster;
+	protected FloatingTextureRenderer floatingRenderer;
 	protected PostProcessor postProcessor;
 	protected Camera camera;
 	protected Skybox sky;
@@ -40,6 +43,7 @@ public class TankernnGame3D extends TankernnGame {
 	protected List<Entity3D> entities = new ArrayList<>();
 	protected List<Projectile> projectiles = new ArrayList<>();
 	protected List<Light> lights = new ArrayList<>();
+	protected List<FloatingTexture> floatTextures = new ArrayList<>();
 	private Light sun;
 	protected TerrainPack terrainPack;
 	protected Player player;
@@ -95,6 +99,7 @@ public class TankernnGame3D extends TankernnGame {
 		renderer.renderScene(scene, new Vector4f(0, 1, 0, Float.MAX_VALUE));
 		waterMaster.renderWater(camera, lights);
 		particleMaster.renderParticles(camera);
+		floatingRenderer.render(floatTextures, camera);
 
 		multisampleFbo.unbindFrameBuffer();
 

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

@@ -13,7 +13,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(TexturedModel model, Vector3f position, Vector3f rotation, float scale, AABB boundingBox, TerrainPack terrainPack) {
+	public Car(TexturedModel model, Vector3f position, Vector3f rotation, Vector3f scale, AABB boundingBox, TerrainPack terrainPack) {
 		super(model, position, rotation, scale, boundingBox, terrainPack);
 	}
 

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

@@ -19,7 +19,7 @@ public class Entity3D implements IPositionable {
 	private TexturedModel model;
 	protected Vector3f position, velocity = new Vector3f(0, 0, 0);
 	private Vector3f rotation;
-	private float scale;
+	private Vector3f scale;
 	private AABB boundingBox;
 	protected boolean dead;
 	protected TerrainPack terrain;
@@ -27,10 +27,10 @@ public class Entity3D implements IPositionable {
 	private final int id;
 	
 	public Entity3D(TexturedModel model, Vector3f position, AABB boundingBox, TerrainPack terrain) {
-		this(model, position, new Vector3f(0, 0, 0), 1, boundingBox, terrain);
+		this(model, position, new Vector3f(0, 0, 0), new Vector3f(0, 0, 0), boundingBox, terrain);
 	}
 	
-	public Entity3D(TexturedModel model, Vector3f position, Vector3f rotation, float scale, AABB boundingBox, TerrainPack terrain) {
+	public Entity3D(TexturedModel model, Vector3f position, Vector3f rotation, Vector3f scale, AABB boundingBox, TerrainPack terrain) {
 		this.model = model;
 		this.position = position;
 		this.rotation = rotation;
@@ -93,11 +93,11 @@ public class Entity3D implements IPositionable {
 		return rotation;
 	}
 	
-	public float getScale() {
+	public Vector3f getScale() {
 		return scale;
 	}
 	
-	public void setScale(float scale) {
+	public void setScale(Vector3f scale) {
 		this.scale = scale;
 	}
 	

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

@@ -20,10 +20,14 @@ public class Player extends Entity3D {
 	protected float currentSpeed = 0;
 	protected float currentTurnSpeed = 0;
 	
-	public Player(TexturedModel model, Vector3f position, Vector3f rotation, float scale, AABB boundingBox, TerrainPack terrainPack) {
+	public Player(TexturedModel model, Vector3f position, Vector3f rotation, Vector3f scale, AABB boundingBox, TerrainPack terrainPack) {
 		super(model, position, rotation, scale, boundingBox, terrainPack);
 	}
 	
+	public Player(TexturedModel model, Vector3f position, AABB boundingBox, TerrainPack terrainPack) {
+		this(model, position, new Vector3f(0, 0, 0), new Vector3f(1, 1, 1), boundingBox, terrainPack);
+	}
+
 	public void move() {
 		checkInputs();
 		super.increaseRotation(new Vector3f(0, currentTurnSpeed * DisplayManager.getFrameTimeSeconds(), 0));

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/entities/projectiles/Projectile.java

@@ -17,7 +17,7 @@ public abstract class Projectile extends Entity3D {
 	private final Vector3f startPosition;
 	
 	public Projectile(TerrainPack terrain, TexturedModel model, Vector3f position, Vector3f velocity, float range, AABB boundingBox, ParticleSystem particleSystem) {
-		super(model, position, new Vector3f(0, 0, 0), 1, boundingBox, terrain);
+		super(model, position, boundingBox, terrain);
 		this.particleSystem = particleSystem;
 		this.velocity = velocity;
 		this.range = range;

+ 2 - 8
src/main/java/eu/tankernn/gameEngine/particles/ParticleRenderer.java

@@ -7,8 +7,6 @@ import java.util.Map;
 import org.lwjgl.BufferUtils;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL15;
-import org.lwjgl.opengl.GL20;
-import org.lwjgl.opengl.GL30;
 import org.lwjgl.opengl.GL31;
 import org.lwjgl.util.vector.Matrix4f;
 import org.lwjgl.util.vector.Vector3f;
@@ -123,9 +121,7 @@ public class ParticleRenderer {
 	
 	private void prepare() {
 		shader.start();
-		GL30.glBindVertexArray(quad.id);
-		for (int i = 0; i < 7; i++)
-			GL20.glEnableVertexAttribArray(i);
+		quad.bind(0, 1, 2, 3, 4, 5, 6);
 		GL11.glEnable(GL11.GL_BLEND);
 		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
 		GL11.glDepthMask(false);
@@ -134,9 +130,7 @@ public class ParticleRenderer {
 	private void finishRendering() {
 		GL11.glDepthMask(true);
 		GL11.glDisable(GL11.GL_BLEND);
-		for (int i = 0; i < 7; i++)
-			GL20.glDisableVertexAttribArray(i);
-		GL30.glBindVertexArray(0);
+		quad.unbind(0, 1, 2, 3, 4, 5, 6);
 		shader.stop();
 	}
 	

+ 1 - 3
src/main/java/eu/tankernn/gameEngine/renderEngine/entities/EntityRenderer.java

@@ -9,7 +9,6 @@ import java.util.Map;
 
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.util.vector.Matrix4f;
-import org.lwjgl.util.vector.Vector3f;
 import org.lwjgl.util.vector.Vector4f;
 
 import eu.tankernn.gameEngine.animation.model.AnimatedModel;
@@ -128,8 +127,7 @@ public class EntityRenderer<S extends EntityShader> {
 	}
 	
 	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(), entity.getRotation(), entity.getScale());
 		shader.transformationMatrix.loadMatrix(transformationMatrix);
 		shader.offset.loadVec2(model.getTextureXOffset(), model.getTextureYOffset());
 	}

+ 40 - 0
src/main/java/eu/tankernn/gameEngine/renderEngine/gui/floating/FloatingTexture.java

@@ -0,0 +1,40 @@
+package eu.tankernn.gameEngine.renderEngine.gui.floating;
+
+import org.lwjgl.util.vector.Vector2f;
+import org.lwjgl.util.vector.Vector3f;
+
+import eu.tankernn.gameEngine.loader.textures.Texture;
+
+public class FloatingTexture {
+	
+	private Texture texture;
+	protected Vector3f position;
+	protected Vector2f scale;
+	
+	public FloatingTexture(Texture texture, Vector3f position, Vector2f scale) {
+		this.texture = texture;
+		this.position = position;
+		this.scale = scale;
+	}
+
+	public Texture getTexture() {
+		return texture;
+	}
+
+	public Vector3f getPosition() {
+		return position;
+	}
+
+	public Vector3f getScale() {
+		return new Vector3f(scale.x, scale.y, 1f);
+	}
+
+	public void setPosition(Vector3f position) {
+		this.position = position;
+	}
+
+	public void setScale(Vector2f scale) {
+		this.scale = scale;
+	}
+	
+}

+ 60 - 0
src/main/java/eu/tankernn/gameEngine/renderEngine/gui/floating/FloatingTextureRenderer.java

@@ -0,0 +1,60 @@
+package eu.tankernn.gameEngine.renderEngine.gui.floating;
+
+import java.util.List;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.vector.Matrix4f;
+
+import eu.tankernn.gameEngine.loader.Loader;
+import eu.tankernn.gameEngine.renderEngine.Vao;
+import eu.tankernn.gameEngine.util.ICamera;
+import eu.tankernn.gameEngine.util.Maths;
+
+public class FloatingTextureRenderer {
+	
+	private final Vao quad;
+	private FloatingTextureShader shader;
+	
+	public FloatingTextureRenderer(Loader loader, Matrix4f projectionMatrix) {
+		float[] positions = {-1, 1, -1, -1, 1, 1, 1, -1};
+		quad = loader.loadToVAO(positions, 2);
+		shader = new FloatingTextureShader();
+		shader.start();
+		shader.projectionMatrix.loadMatrix(projectionMatrix);
+		shader.stop();
+	}
+	
+	public void render(List<FloatingTexture> textures, ICamera camera) {
+		Matrix4f viewMatrix = camera.getViewMatrix();
+		shader.start();
+		quad.bind(0);
+		GL11.glEnable(GL11.GL_BLEND);
+		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+		for (FloatingTexture texture: textures) {
+			texture.getTexture().bindToUnit(0);
+			Matrix4f modelMatrix = new Matrix4f();
+			modelMatrix.setIdentity();
+			Matrix4f.translate(texture.getPosition(), modelMatrix, modelMatrix);
+			//Sets rotation of model matrix to transpose of rotation of view matrix
+			modelMatrix.m00 = viewMatrix.m00;
+			modelMatrix.m01 = viewMatrix.m10;
+			modelMatrix.m02 = viewMatrix.m20;
+			modelMatrix.m10 = viewMatrix.m01;
+			modelMatrix.m11 = viewMatrix.m11;
+			modelMatrix.m12 = viewMatrix.m21;
+			modelMatrix.m20 = viewMatrix.m02;
+			modelMatrix.m21 = viewMatrix.m12;
+			modelMatrix.m22 = viewMatrix.m22;
+			Matrix4f.scale(texture.getScale(), modelMatrix, modelMatrix);
+			shader.modelViewMatrix.loadMatrix(Matrix4f.mul(viewMatrix, modelMatrix, null));
+			GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, quad.getIndexCount());
+		}
+		GL11.glDisable(GL11.GL_BLEND);
+		quad.unbind(0);
+		shader.stop();
+	}
+	
+	public void finalize() {
+		shader.finalize();
+	}
+}

+ 18 - 0
src/main/java/eu/tankernn/gameEngine/renderEngine/gui/floating/FloatingTextureShader.java

@@ -0,0 +1,18 @@
+package eu.tankernn.gameEngine.renderEngine.gui.floating;
+
+import eu.tankernn.gameEngine.renderEngine.shaders.ShaderProgram;
+import eu.tankernn.gameEngine.renderEngine.shaders.UniformMatrix;
+
+public class FloatingTextureShader extends ShaderProgram {
+	private static final String VERTEX_FILE = "/eu/tankernn/gameEngine/renderEngine/gui/floating/floatingVertex.glsl";
+	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/renderEngine/gui/floating/floatingFragment.glsl";
+	
+	protected UniformMatrix projectionMatrix = new UniformMatrix("projectionMatrix");
+	protected UniformMatrix modelViewMatrix = new UniformMatrix("modelViewMatrix");
+	
+	public FloatingTextureShader() {
+		super(VERTEX_FILE, FRAGMENT_FILE, "position");
+		super.storeAllUniformLocations(projectionMatrix, modelViewMatrix);
+	}
+	
+}

+ 13 - 0
src/main/java/eu/tankernn/gameEngine/renderEngine/gui/floating/floatingFragment.glsl

@@ -0,0 +1,13 @@
+#version 140
+
+in vec2 textureCoords;
+
+out vec4 out_Color;
+
+uniform sampler2D guiTexture;
+
+void main(void){
+
+	out_Color = texture(guiTexture,textureCoords);
+
+}

+ 13 - 0
src/main/java/eu/tankernn/gameEngine/renderEngine/gui/floating/floatingVertex.glsl

@@ -0,0 +1,13 @@
+#version 140
+
+in vec2 position;
+
+out vec2 textureCoords;
+
+uniform mat4 projectionMatrix;
+uniform mat4 modelViewMatrix;
+
+void main(void){
+	gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 0.0, 1.0);
+	textureCoords = vec2((position.x+1.0)/2.0, 1 - (position.y+1.0)/2.0);
+}

+ 1 - 3
src/main/java/eu/tankernn/gameEngine/renderEngine/shadows/ShadowMapEntityRenderer.java

@@ -7,7 +7,6 @@ import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL20;
 import org.lwjgl.opengl.GL30;
 import org.lwjgl.util.vector.Matrix4f;
-import org.lwjgl.util.vector.Vector3f;
 
 import eu.tankernn.gameEngine.animation.model.AnimatedModel;
 import eu.tankernn.gameEngine.entities.Entity3D;
@@ -87,8 +86,7 @@ public class ShadowMapEntityRenderer {
 	 * @param entity - the entity to be prepared for rendering.
 	 */
 	private void prepareInstance(Entity3D entity) {
-		Vector3f rot = entity.getRotation();
-		Matrix4f modelMatrix = Maths.createTransformationMatrix(entity.getPosition(), rot.x, rot.y, rot.z, entity.getScale());
+		Matrix4f modelMatrix = Maths.createTransformationMatrix(entity.getPosition(), entity.getRotation(), entity.getScale());
 		Matrix4f mvpMatrix = Matrix4f.mul(projectionViewMatrix, modelMatrix, null);
 		shader.mvpMatrix.loadMatrix(mvpMatrix);
 	}

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/renderEngine/terrain/TerrainRenderer.java

@@ -77,7 +77,7 @@ public class TerrainRenderer {
 
 	private void loadModelMatrix(Terrain terrain) {
 		Matrix4f transformationMatrix = Maths
-				.createTransformationMatrix(new Vector3f(terrain.getX(), 0, terrain.getZ()), 0, 0, 0, 1);
+				.createTransformationMatrix(new Vector3f(terrain.getX(), 0, terrain.getZ()), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1));
 		shader.transformationMatrix.loadMatrix(transformationMatrix);
 	}
 }

+ 2 - 2
src/main/java/eu/tankernn/gameEngine/renderEngine/water/WaterMaster.java

@@ -59,8 +59,8 @@ public class WaterMaster {
 	public boolean isPointUnderWater(Vector3f point) {
 		for (WaterTile tile : waterTiles) {
 			if (point.y < tile.getHeight()) {
-				if (tile.getX() - tile.getSize() <= point.x && point.x <= tile.getX() + tile.getSize()) {
-					if (tile.getZ() - tile.getSize() <= point.z && point.z <= tile.getZ() + tile.getSize()) {
+				if (tile.getX() - tile.getSize().x <= point.x && point.x <= tile.getX() + tile.getSize().x) {
+					if (tile.getZ() - tile.getSize().z <= point.z && point.z <= tile.getZ() + tile.getSize().z) {
 						return true;
 					}
 				}

+ 10 - 12
src/main/java/eu/tankernn/gameEngine/renderEngine/water/WaterRenderer.java

@@ -32,7 +32,7 @@ public class WaterRenderer {
 	
 	private Texture dudvTexture;
 	private Texture normalMap;
-
+	
 	public WaterRenderer(Loader loader, Texture dudvTexture, Texture normalMap, WaterShader shader, Matrix4f projectionMatrix, WaterFrameBuffers buffers) {
 		this.shader = shader;
 		this.buffers = buffers;
@@ -44,20 +44,18 @@ public class WaterRenderer {
 		shader.stop();
 		setUpVAO(loader);
 	}
-
+	
 	public void render(List<WaterTile> water, Camera camera, List<Light> lights) {
-		prepareRender(camera, lights);	
-		for (WaterTile tile : water) {
-			Matrix4f modelMatrix = Maths.createTransformationMatrix(
-					new Vector3f(tile.getX(), tile.getHeight(), tile.getZ()), 0, 0, 0,
-					tile.getSize());
+		prepareRender(camera, lights);
+		for (WaterTile tile: water) {
+			Matrix4f modelMatrix = Maths.createTransformationMatrix(new Vector3f(tile.getX(), tile.getHeight(), tile.getZ()), new Vector3f(0, 0, 0), tile.getSize());
 			shader.modelMatrix.loadMatrix(modelMatrix);
 			GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, quad.getIndexCount());
 		}
 		unbind();
 	}
 	
-	private void prepareRender(Camera camera, List<Light> lights){
+	private void prepareRender(Camera camera, List<Light> lights) {
 		shader.start();
 		shader.viewMatrix.loadCamera(camera);
 		shader.cameraPosition.loadVec3(camera.getPosition());
@@ -81,17 +79,17 @@ public class WaterRenderer {
 		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
 	}
 	
-	private void unbind(){
+	private void unbind() {
 		GL11.glDisable(GL11.GL_BLEND);
 		GL20.glDisableVertexAttribArray(0);
 		GL30.glBindVertexArray(0);
 		shader.stop();
 	}
-
+	
 	private void setUpVAO(Loader loader) {
 		// Just x and z vertex positions here, y is set to 0 in v.shader
-		float[] vertices = { -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1 };
+		float[] vertices = {-1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1};
 		quad = loader.loadToVAO(vertices, 2);
 	}
-
+	
 }

+ 2 - 2
src/main/java/eu/tankernn/gameEngine/renderEngine/water/WaterTile.java

@@ -29,8 +29,8 @@ public class WaterTile implements IPositionable {
 		return z;
 	}
 	
-	public float getSize() {
-		return size;
+	public Vector3f getSize() {
+		return new Vector3f(size, 0, size);
 	}
 
 	@Override

+ 22 - 11
src/main/java/eu/tankernn/gameEngine/util/Maths.java

@@ -23,16 +23,19 @@ public class Maths {
 		// Calculate angle between them.
 		double cosHalfTheta = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z;
 		// if qa=qb or qa=-qb then theta = 0 and we can return qa
-		if (Math.abs(cosHalfTheta) >= 1.0){
-			qm.w = qa.w;qm.x = qa.x;qm.y = qa.y;qm.z = qa.z;
+		if (Math.abs(cosHalfTheta) >= 1.0) {
+			qm.w = qa.w;
+			qm.x = qa.x;
+			qm.y = qa.y;
+			qm.z = qa.z;
 			return qm;
 		}
 		// Calculate temporary values.
 		double halfTheta = Math.acos(cosHalfTheta);
-		double sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta*cosHalfTheta);
+		double sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta);
 		// if theta = 180 degrees then result is not fully defined
 		// we could rotate around any axis normal to qa or qb
-		if (Math.abs(sinHalfTheta) < 0.001){ // fabs is floating point absolute
+		if (Math.abs(sinHalfTheta) < 0.001) { // fabs is floating point absolute
 			qm.w = (float) (qa.w * 0.5 + qb.w * 0.5);
 			qm.x = (float) (qa.x * 0.5 + qb.x * 0.5);
 			qm.y = (float) (qa.y * 0.5 + qb.y * 0.5);
@@ -40,7 +43,7 @@ public class Maths {
 			return qm;
 		}
 		double ratioA = Math.sin((1 - time) * halfTheta) / sinHalfTheta;
-		double ratioB = Math.sin(time * halfTheta) / sinHalfTheta; 
+		double ratioB = Math.sin(time * halfTheta) / sinHalfTheta;
 		//calculate Quaternion.
 		qm.w = (float) (qa.w * ratioA + qb.w * ratioB);
 		qm.x = (float) (qa.x * ratioA + qb.x * ratioB);
@@ -57,6 +60,10 @@ public class Maths {
 		return matrix;
 	}
 	
+	public static Matrix4f createTransformationMatrix(Vector3f translation, Vector3f scale) {
+		return createTransformationMatrix(translation, null, scale);
+	}
+	
 	public static float barryCentric(Vector3f p1, Vector3f p2, Vector3f p3, Vector2f pos) {
 		float det = (p2.z - p3.z) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.z - p3.z);
 		float l1 = ((p2.z - p3.z) * (pos.x - p3.x) + (p3.x - p2.x) * (pos.y - p3.z)) / det;
@@ -65,14 +72,18 @@ public class Maths {
 		return l1 * p1.y + l2 * p2.y + l3 * p3.y;
 	}
 	
-	public static Matrix4f createTransformationMatrix(Vector3f translation, float rx, float ry, float rz, float scale) {
+	public static Matrix4f createTransformationMatrix(Vector3f translation, Vector3f rotation, Vector3f scale) {
 		Matrix4f matrix = new Matrix4f();
 		matrix.setIdentity();
-		Matrix4f.translate(translation, matrix, matrix);
-		Matrix4f.rotate((float) Math.toRadians(rx), new Vector3f(1, 0, 0), matrix, matrix);
-		Matrix4f.rotate((float) Math.toRadians(ry), new Vector3f(0, 1, 0), matrix, matrix);
-		Matrix4f.rotate((float) Math.toRadians(rz), new Vector3f(0, 0, 1), matrix, matrix);
-		Matrix4f.scale(new Vector3f(scale, scale, scale), matrix, matrix);
+		if (translation != null)
+			Matrix4f.translate(translation, matrix, matrix);
+		if (rotation != null) {
+			Matrix4f.rotate((float) Math.toRadians(rotation.x), new Vector3f(1, 0, 0), matrix, matrix);
+			Matrix4f.rotate((float) Math.toRadians(rotation.y), new Vector3f(0, 1, 0), matrix, matrix);
+			Matrix4f.rotate((float) Math.toRadians(rotation.z), new Vector3f(0, 0, 1), matrix, matrix);
+		}
+		if (scale != null)
+			Matrix4f.scale(scale, matrix, matrix);
 		return matrix;
 	}
 }